extract d3d11 common helpers

This commit is contained in:
gnattu
2026-07-01 16:26:36 +08:00
parent ea5ac4f540
commit bfc89c9e74
4 changed files with 294 additions and 866 deletions
+146 -190
View File
@@ -27,7 +27,7 @@ Index: FFmpeg/libavfilter/Makefile
OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \
opencl/avgblur.o boxblur.o
OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o bwdifdsp.o yadif_common.o
+OBJS-$(CONFIG_BWDIF_D3D11_FILTER) += vf_yadif_d3d11.o yadif_common.o d3d11/deint.o
+OBJS-$(CONFIG_BWDIF_D3D11_FILTER) += vf_yadif_d3d11.o yadif_common.o d3d11/deint.o d3d11_filter.o
OBJS-$(CONFIG_BWDIF_CUDA_FILTER) += vf_bwdif_cuda.o vf_bwdif_cuda.ptx.o \
yadif_common.o
OBJS-$(CONFIG_BWDIF_OPENCL_FILTER) += vf_bwdif_opencl.o opencl.o opencl/bwdif.o \
@@ -35,7 +35,7 @@ Index: FFmpeg/libavfilter/Makefile
OBJS-$(CONFIG_XPSNR_FILTER) += vf_xpsnr.o framesync.o psnr.o
OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o
OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o
+OBJS-$(CONFIG_YADIF_D3D11_FILTER) += vf_yadif_d3d11.o yadif_common.o d3d11/deint.o
+OBJS-$(CONFIG_YADIF_D3D11_FILTER) += vf_yadif_d3d11.o yadif_common.o d3d11/deint.o d3d11_filter.o
OBJS-$(CONFIG_YADIF_CUDA_FILTER) += vf_yadif_cuda.o vf_yadif_cuda.ptx.o \
yadif_common.o cuda/load_helper.o
OBJS-$(CONFIG_YADIF_OPENCL_FILTER) += vf_yadif_opencl.o opencl.o opencl/yadif.o \
@@ -81,7 +81,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/vf_yadif_d3d11.c
@@ -0,0 +1,804 @@
@@ -0,0 +1,660 @@
+/*
+ * D3D11 YADIF/BWDIF deinterlacing filters
+ *
@@ -109,7 +109,6 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+#define COBJMACROS
+#endif
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/common.h"
@@ -124,21 +123,11 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+#include "yadif.h"
+#include "vf_yadif_d3d11.h"
+#include "d3d11_source.h"
+
+#define D3D11_RELEASE(p) do { if (p) { (p)->lpVtbl->Release(p); (p) = NULL; } } while (0)
+#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
+#endif
+
+#include "d3d11_filter.h"
+
+#define DEINT_D3D11_ALG_YADIF 0
+#define DEINT_D3D11_ALG_BWDIF 1
+
+typedef HRESULT (WINAPI *D3DCompileProc)(LPCVOID, SIZE_T, LPCSTR,
+ const D3D_SHADER_MACRO *, ID3DInclude *,
+ LPCSTR, LPCSTR, UINT, UINT,
+ ID3D10Blob **, ID3D10Blob **);
+
+typedef struct DeintD3D11Params {
+ int width;
+ int height;
@@ -163,7 +152,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ ID3D11Device *device;
+ ID3D11DeviceContext *context;
+ HMODULE d3dcompiler;
+ D3DCompileProc D3DCompile;
+ FFD3DCompileProc D3DCompile;
+
+ ID3D11ComputeShader *cs_y;
+ ID3D11ComputeShader *cs_uv;
@@ -181,95 +170,43 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+
+static void release_d3d11_resources(DeintD3D11Context *s)
+{
+ D3D11_RELEASE(s->cs_y);
+ D3D11_RELEASE(s->cs_uv);
+ D3D11_RELEASE(s->params_buf);
+ D3D11_RELEASE(s->prev_tex);
+ D3D11_RELEASE(s->cur_tex);
+ D3D11_RELEASE(s->next_tex);
+ D3D11_RELEASE(s->work_tex);
+ FF_D3D11_RELEASE(s->cs_y);
+ FF_D3D11_RELEASE(s->cs_uv);
+ FF_D3D11_RELEASE(s->params_buf);
+ FF_D3D11_RELEASE(s->prev_tex);
+ FF_D3D11_RELEASE(s->cur_tex);
+ FF_D3D11_RELEASE(s->next_tex);
+ FF_D3D11_RELEASE(s->work_tex);
+ s->tex_w = s->tex_h = 0;
+}
+
+static int compile_shader(AVFilterContext *ctx, const char *entry, ID3D11ComputeShader **shader)
+{
+ DeintD3D11Context *s = ctx->priv;
+ ID3D10Blob *cs_blob = NULL;
+ ID3D10Blob *err_blob = NULL;
+ HRESULT hr;
+
+ hr = s->D3DCompile(ff_source_deint_hlsl, strlen(ff_source_deint_hlsl),
+ NULL, NULL, NULL, entry, "cs_5_0",
+ D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &cs_blob, &err_blob);
+ if (FAILED(hr)) {
+ if (err_blob) {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 deinterlace shader %s: %.*s\n",
+ entry, (int)err_blob->lpVtbl->GetBufferSize(err_blob),
+ (char *)err_blob->lpVtbl->GetBufferPointer(err_blob));
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 deinterlace shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ }
+ D3D11_RELEASE(err_blob);
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = s->device->lpVtbl->CreateComputeShader(s->device,
+ cs_blob->lpVtbl->GetBufferPointer(cs_blob),
+ cs_blob->lpVtbl->GetBufferSize(cs_blob),
+ NULL, shader);
+ D3D11_RELEASE(cs_blob);
+ D3D11_RELEASE(err_blob);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 deinterlace shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_compile_shader(ctx, s->device, s->D3DCompile,
+ ff_source_deint_hlsl, NULL, entry,
+ "cs_5_0", "D3D11 deinterlace", shader);
+}
+
+static int init_shaders(AVFilterContext *ctx)
+{
+ DeintD3D11Context *s = ctx->priv;
+ D3D11_BUFFER_DESC bd = { 0 };
+ HRESULT hr;
+ int ret;
+
+ if (s->cs_y)
+ return 0;
+
+ if (!s->d3dcompiler) {
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_47.dll");
+ if (!s->d3dcompiler)
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_43.dll");
+ }
+ if (!s->d3dcompiler) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading d3dcompiler DLL\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ s->D3DCompile = (D3DCompileProc)GetProcAddress(s->d3dcompiler, "D3DCompile");
+ if (!s->D3DCompile) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading D3DCompile\n");
+ return AVERROR_EXTERNAL;
+ }
+ ret = ff_d3d11_load_shader_compiler(ctx, &s->d3dcompiler, &s->D3DCompile);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = compile_shader(ctx, "deint_y", &s->cs_y)) < 0 ||
+ (ret = compile_shader(ctx, "deint_uv", &s->cs_uv)) < 0)
+ return ret;
+
+ bd.ByteWidth = sizeof(DeintD3D11Params);
+ bd.Usage = D3D11_USAGE_DYNAMIC;
+ bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ hr = s->device->lpVtbl->CreateBuffer(s->device, &bd, NULL, &s->params_buf);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 deinterlace constant buffer: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+ return ff_d3d11_create_const_buffer(ctx, s->device, sizeof(DeintD3D11Params),
+ "D3D11 deinterlace", &s->params_buf);
+}
+
+static int ensure_textures(AVFilterContext *ctx, int w, int h)
@@ -281,10 +218,10 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ if (s->prev_tex && s->cur_tex && s->next_tex && s->work_tex && s->tex_w == w && s->tex_h == h)
+ return 0;
+
+ D3D11_RELEASE(s->prev_tex);
+ D3D11_RELEASE(s->cur_tex);
+ D3D11_RELEASE(s->next_tex);
+ D3D11_RELEASE(s->work_tex);
+ FF_D3D11_RELEASE(s->prev_tex);
+ FF_D3D11_RELEASE(s->cur_tex);
+ FF_D3D11_RELEASE(s->next_tex);
+ FF_D3D11_RELEASE(s->work_tex);
+
+ desc.Width = w;
+ desc.Height = h;
@@ -316,65 +253,15 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return AVERROR_EXTERNAL;
+}
+
+static void fill_tex2d_srv_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0;
+ UINT array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MostDetailedMip = mip_slice;
+ desc->Texture2DArray.MipLevels = 1;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+}
+
+static void fill_tex2d_uav_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0;
+ UINT array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MipSlice = mip_slice;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+}
+
+static int create_nv12_srv_view(AVFilterContext *ctx, ID3D11Texture2D *tex,
+ UINT subresource, int plane, int log_level,
+ ID3D11ShaderResourceView **srv)
+{
+ DeintD3D11Context *s = ctx->priv;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ fill_tex2d_srv_desc(tex, subresource, plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM, &desc);
+
+ hr = s->device->lpVtbl->CreateShaderResourceView(s->device, (ID3D11Resource *)tex,
+ &desc, srv);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 deinterlace SRV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_srv(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(AV_PIX_FMT_NV12, plane),
+ log_level, "D3D11 deinterlace", srv);
+}
+
+static int create_nv12_srv(AVFilterContext *ctx, ID3D11Texture2D *tex, int plane,
@@ -388,19 +275,10 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ ID3D11UnorderedAccessView **uav)
+{
+ DeintD3D11Context *s = ctx->priv;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ fill_tex2d_uav_desc(tex, subresource, plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM, &desc);
+
+ hr = s->device->lpVtbl->CreateUnorderedAccessView(s->device, (ID3D11Resource *)tex,
+ &desc, uav);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 deinterlace UAV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_uav(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(AV_PIX_FMT_NV12, plane),
+ log_level, "D3D11 deinterlace", uav);
+}
+
+static int create_nv12_uav(AVFilterContext *ctx, ID3D11Texture2D *tex, int plane,
@@ -409,27 +287,6 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return create_nv12_uav_view(ctx, tex, 0, plane, AV_LOG_ERROR, uav);
+}
+
+static void copy_frame_to_texture(DeintD3D11Context *s, AVFrame *src, ID3D11Texture2D *dst)
+{
+ ID3D11Texture2D *src_tex = (ID3D11Texture2D *)src->data[0];
+ UINT src_sub = (UINT)(uintptr_t)src->data[1];
+ D3D11_BOX box = { 0, 0, 0, src->width, src->height, 1 };
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst, 0,
+ 0, 0, 0, (ID3D11Resource *)src_tex,
+ src_sub, &box);
+}
+
+static void copy_texture_to_frame(DeintD3D11Context *s, ID3D11Texture2D *src, AVFrame *dst)
+{
+ ID3D11Texture2D *dst_tex = (ID3D11Texture2D *)dst->data[0];
+ UINT dst_sub = (UINT)(uintptr_t)dst->data[1];
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst_tex,
+ dst_sub, 0, 0, 0, (ID3D11Resource *)src,
+ 0, NULL);
+}
+
+static int create_frame_srvs(AVFilterContext *ctx, AVFrame *frame,
+ ID3D11ShaderResourceView **srv_y,
+ ID3D11ShaderResourceView **srv_uv)
@@ -443,7 +300,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return ret;
+ ret = create_nv12_srv_view(ctx, tex, subresource, 1, AV_LOG_DEBUG, srv_uv);
+ if (ret < 0)
+ D3D11_RELEASE(*srv_y);
+ FF_D3D11_RELEASE(*srv_y);
+ return ret;
+}
+
@@ -467,15 +324,15 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return 0;
+ }
+ for (int i = 0; i < 6; i++)
+ D3D11_RELEASE(srvs[i]);
+ FF_D3D11_RELEASE(srvs[i]);
+ if (s->direct_input_srv < 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader input: copied to internal SRV texture\n");
+ s->direct_input_srv = 0;
+ }
+
+ copy_frame_to_texture(s, y->prev, s->prev_tex);
+ copy_frame_to_texture(s, y->cur, s->cur_tex);
+ copy_frame_to_texture(s, y->next, s->next_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, y->prev, s->prev_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, y->cur, s->cur_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, y->next, s->next_tex);
+
+#define MAKE_SRV(tex, plane, idx) do { ret = create_nv12_srv(ctx, tex, plane, &srvs[idx]); if (ret < 0) goto fail; } while (0)
+ MAKE_SRV(s->prev_tex, 0, 0);
@@ -491,7 +348,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+fail:
+#undef MAKE_SRV
+ for (int i = 0; i < 6; i++)
+ D3D11_RELEASE(srvs[i]);
+ FF_D3D11_RELEASE(srvs[i]);
+ return ret;
+}
+
@@ -512,8 +369,8 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ *direct = 1;
+ return 0;
+ }
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ if (s->direct_output_uav < 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: copied from internal UAV texture\n");
+ s->direct_output_uav = 0;
@@ -524,7 +381,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ return ret;
+ ret = create_nv12_uav(ctx, s->work_tex, 1, &uavs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[0]);
+ return ret;
+}
+
@@ -559,8 +416,8 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ ret = create_nv12_uav_view(ctx, tex, subresource, 1, AV_LOG_DEBUG, &uavs[1]);
+
+done:
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&frame);
+ return ret;
+}
@@ -632,7 +489,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+
+ if (!direct_output)
+ copy_texture_to_frame(s, s->work_tex, dst);
+ ff_d3d11_copy_texture_to_frame(s->context, s->work_tex, dst);
+
+fail:
+ s->context->lpVtbl->CSSetShader(s->context, NULL, NULL, 0);
@@ -640,9 +497,9 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ s->context->lpVtbl->CSSetUnorderedAccessViews(s->context, 0, 2, null_uavs, NULL);
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+ for (int i = 0; i < 6; i++)
+ D3D11_RELEASE(srvs[i]);
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[i]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ return ret;
+}
+
@@ -667,8 +524,7 @@ Index: FFmpeg/libavfilter/vf_yadif_d3d11.c
+ av_buffer_unref(&s->input_frames_ref);
+ s->hwctx = NULL;
+ s->input_frames = NULL;
+ if (s->d3dcompiler)
+ FreeLibrary(s->d3dcompiler);
+ ff_d3d11_unload_shader_compiler(&s->d3dcompiler, &s->D3DCompile);
+}
+
+static int config_input(AVFilterLink *inlink)
@@ -1332,3 +1188,103 @@ Index: FFmpeg/libavfilter/d3d11_source.h
+extern const char *ff_source_deint_hlsl;
+
+#endif /* AVFILTER_D3D11_SOURCE_H */
Index: FFmpeg/libavfilter/d3d11_filter.c
===================================================================
--- FFmpeg.orig/libavfilter/d3d11_filter.c
+++ FFmpeg/libavfilter/d3d11_filter.c
@@ -11,6 +11,9 @@
#include "config.h"
+#include <stdint.h>
+#include <string.h>
+
#include "libavutil/error.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
Index: FFmpeg/libavfilter/d3d11_filter.h
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/d3d11_filter.h
@@ -0,0 +1,81 @@
+/*
+ * Common D3D11 filter helpers
+ *
+ * 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.
+ */
+
+#ifndef AVFILTER_D3D11_FILTER_H
+#define AVFILTER_D3D11_FILTER_H
+
+#include <windows.h>
+#ifndef COBJMACROS
+#define COBJMACROS
+#endif
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+#include "libavutil/frame.h"
+#include "libavutil/pixfmt.h"
+#include "avfilter.h"
+
+#define FF_D3D11_RELEASE(p) do { if (p) { (p)->lpVtbl->Release(p); (p) = NULL; } } while (0)
+
+#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
+#endif
+
+typedef HRESULT (WINAPI *FFD3DCompileProc)(LPCVOID, SIZE_T, LPCSTR,
+ const D3D_SHADER_MACRO *, ID3DInclude *,
+ LPCSTR, LPCSTR, UINT, UINT,
+ ID3D10Blob **, ID3D10Blob **);
+
+int ff_d3d11_load_shader_compiler(AVFilterContext *ctx, HMODULE *d3dcompiler,
+ FFD3DCompileProc *compile);
+void ff_d3d11_unload_shader_compiler(HMODULE *d3dcompiler, FFD3DCompileProc *compile);
+
+int ff_d3d11_compile_shader(AVFilterContext *ctx, ID3D11Device *device,
+ FFD3DCompileProc compile, const char *source,
+ const D3D_SHADER_MACRO *macros, const char *entry,
+ const char *target, const char *name,
+ ID3D11ComputeShader **shader);
+
+int ff_d3d11_create_const_buffer(AVFilterContext *ctx, ID3D11Device *device,
+ size_t size, const char *name,
+ ID3D11Buffer **buffer);
+
+DXGI_FORMAT ff_d3d11_texture_format(enum AVPixelFormat fmt);
+DXGI_FORMAT ff_d3d11_plane_format(enum AVPixelFormat fmt, int plane);
+
+int ff_d3d11_ensure_texture(AVFilterContext *ctx, ID3D11Device *device,
+ ID3D11Texture2D **tex, int *cur_w, int *cur_h,
+ DXGI_FORMAT *cur_fmt, int w, int h,
+ DXGI_FORMAT fmt, UINT bind_flags,
+ const char *name);
+
+void ff_d3d11_fill_srv_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_SHADER_RESOURCE_VIEW_DESC *desc);
+void ff_d3d11_fill_uav_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_UNORDERED_ACCESS_VIEW_DESC *desc);
+
+int ff_d3d11_create_srv(AVFilterContext *ctx, ID3D11Device *device,
+ ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, int log_level, const char *name,
+ ID3D11ShaderResourceView **srv);
+int ff_d3d11_create_uav(AVFilterContext *ctx, ID3D11Device *device,
+ ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, int log_level, const char *name,
+ ID3D11UnorderedAccessView **uav);
+
+void ff_d3d11_copy_frame_to_texture(ID3D11DeviceContext *context, AVFrame *src,
+ ID3D11Texture2D *dst);
+void ff_d3d11_copy_texture_to_frame(ID3D11DeviceContext *context, ID3D11Texture2D *src,
+ AVFrame *dst);
+void ff_d3d11_copy_frame_to_frame(ID3D11DeviceContext *context, AVFrame *src,
+ AVFrame *dst);
+
+#endif /* AVFILTER_D3D11_FILTER_H */
@@ -28,7 +28,7 @@ Index: FFmpeg/libavfilter/Makefile
OBJS-$(CONFIG_OCIO_FILTER) += vf_opencolorio.o ocio_wrapper.o
OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o
OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o
+OBJS-$(CONFIG_OVERLAY_D3D11_FILTER) += vf_overlay_d3d11.o framesync.o d3d11/overlay.o
+OBJS-$(CONFIG_OVERLAY_D3D11_FILTER) += vf_overlay_d3d11.o framesync.o d3d11/overlay.o d3d11_filter.o
OBJS-$(CONFIG_OVERLAY_CUDA_FILTER) += vf_overlay_cuda.o framesync.o vf_overlay_cuda.ptx.o \
cuda/load_helper.o
OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \
@@ -64,7 +64,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/vf_overlay_d3d11.c
@@ -0,0 +1,976 @@
@@ -0,0 +1,793 @@
+/*
+ * D3D11 overlay filter
+ *
@@ -92,7 +92,6 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+#define COBJMACROS
+#endif
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+#include "libavutil/common.h"
+#include "libavutil/eval.h"
@@ -104,6 +103,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+
+#include "vf_overlay_d3d11.h"
+#include "d3d11_source.h"
+#include "d3d11_filter.h"
+#include "filters.h"
+#include "framesync.h"
+#include "video.h"
@@ -111,11 +111,6 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+#define MAIN 0
+#define OVERLAY 1
+
+#define D3D11_RELEASE(p) do { if (p) { (p)->lpVtbl->Release(p); (p) = NULL; } } while (0)
+#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
+#endif
+
+enum var_name {
+ VAR_MAIN_IW, VAR_MW,
+ VAR_MAIN_IH, VAR_MH,
@@ -128,11 +123,6 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ VAR_VARS_NB
+};
+
+typedef HRESULT (WINAPI *D3DCompileProc)(LPCVOID, SIZE_T, LPCSTR,
+ const D3D_SHADER_MACRO *, ID3DInclude *,
+ LPCSTR, LPCSTR, UINT, UINT,
+ ID3D10Blob **, ID3D10Blob **);
+
+typedef struct OverlayD3D11Context {
+ const AVClass *classCtx;
+ FFFrameSync fs;
@@ -151,7 +141,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ ID3D11Device *device;
+ ID3D11DeviceContext *context;
+ HMODULE d3dcompiler;
+ D3DCompileProc D3DCompile;
+ FFD3DCompileProc D3DCompile;
+
+ ID3D11ComputeShader *cs_bgra_y;
+ ID3D11ComputeShader *cs_bgra_uv;
@@ -190,12 +180,12 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+
+static void overlay_d3d11_release_resources(OverlayD3D11Context *s)
+{
+ D3D11_RELEASE(s->cs_bgra_y);
+ D3D11_RELEASE(s->cs_bgra_uv);
+ D3D11_RELEASE(s->params_buf);
+ D3D11_RELEASE(s->main_tex);
+ D3D11_RELEASE(s->work_tex);
+ D3D11_RELEASE(s->overlay_tex);
+ FF_D3D11_RELEASE(s->cs_bgra_y);
+ FF_D3D11_RELEASE(s->cs_bgra_uv);
+ FF_D3D11_RELEASE(s->params_buf);
+ FF_D3D11_RELEASE(s->main_tex);
+ FF_D3D11_RELEASE(s->work_tex);
+ FF_D3D11_RELEASE(s->overlay_tex);
+ s->main_tex_w = s->main_tex_h = 0;
+ s->work_w = s->work_h = 0;
+ s->overlay_tex_w = s->overlay_tex_h = 0;
@@ -240,82 +230,30 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+static int compile_shader(AVFilterContext *ctx, const char *entry, ID3D11ComputeShader **shader)
+{
+ OverlayD3D11Context *s = ctx->priv;
+ ID3D10Blob *cs_blob = NULL;
+ ID3D10Blob *err_blob = NULL;
+ HRESULT hr;
+
+ hr = s->D3DCompile(ff_source_overlay_hlsl, strlen(ff_source_overlay_hlsl),
+ NULL, NULL, NULL, entry, "cs_5_0",
+ D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &cs_blob, &err_blob);
+ if (FAILED(hr)) {
+ if (err_blob) {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling overlay shader %s: %.*s\n",
+ entry, (int)err_blob->lpVtbl->GetBufferSize(err_blob),
+ (char *)err_blob->lpVtbl->GetBufferPointer(err_blob));
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling overlay shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ }
+ D3D11_RELEASE(err_blob);
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = s->device->lpVtbl->CreateComputeShader(s->device,
+ cs_blob->lpVtbl->GetBufferPointer(cs_blob),
+ cs_blob->lpVtbl->GetBufferSize(cs_blob),
+ NULL, shader);
+ D3D11_RELEASE(cs_blob);
+ D3D11_RELEASE(err_blob);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating overlay shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_compile_shader(ctx, s->device, s->D3DCompile,
+ ff_source_overlay_hlsl, NULL, entry,
+ "cs_5_0", "D3D11 overlay", shader);
+}
+
+static int overlay_d3d11_init_shader(AVFilterContext *ctx)
+{
+ OverlayD3D11Context *s = ctx->priv;
+ D3D11_BUFFER_DESC bd = { 0 };
+ HRESULT hr;
+ int ret;
+
+ if (s->cs_bgra_y)
+ return 0;
+
+ if (!s->d3dcompiler) {
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_47.dll");
+ if (!s->d3dcompiler)
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_43.dll");
+ }
+ if (!s->d3dcompiler) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading d3dcompiler DLL\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ s->D3DCompile = (D3DCompileProc)GetProcAddress(s->d3dcompiler, "D3DCompile");
+ if (!s->D3DCompile) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading D3DCompile\n");
+ return AVERROR_EXTERNAL;
+ }
+ ret = ff_d3d11_load_shader_compiler(ctx, &s->d3dcompiler, &s->D3DCompile);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = compile_shader(ctx, "bgra_y", &s->cs_bgra_y)) < 0 ||
+ (ret = compile_shader(ctx, "bgra_uv", &s->cs_bgra_uv)) < 0)
+ return ret;
+
+ bd.ByteWidth = sizeof(OverlayD3D11Params);
+ bd.Usage = D3D11_USAGE_DYNAMIC;
+ bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ hr = s->device->lpVtbl->CreateBuffer(s->device, &bd, NULL, &s->params_buf);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating overlay constant buffer: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+ return ff_d3d11_create_const_buffer(ctx, s->device, sizeof(OverlayD3D11Params),
+ "D3D11 overlay", &s->params_buf);
+}
+
+static int ensure_texture(AVFilterContext *ctx, ID3D11Texture2D **tex,
@@ -323,76 +261,9 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ int w, int h, DXGI_FORMAT fmt, UINT bind_flags)
+{
+ OverlayD3D11Context *s = ctx->priv;
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ HRESULT hr;
+
+ if (*tex && *cur_w == w && *cur_h == h && (!cur_fmt || *cur_fmt == fmt))
+ return 0;
+
+ D3D11_RELEASE(*tex);
+
+ desc.Width = w;
+ desc.Height = h;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = fmt;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bind_flags;
+
+ hr = s->device->lpVtbl->CreateTexture2D(s->device, &desc, NULL, tex);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating overlay texture %dx%d format %u: HRESULT 0x%lX\n",
+ w, h, fmt, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ *cur_w = w;
+ *cur_h = h;
+ if (cur_fmt)
+ *cur_fmt = fmt;
+ return 0;
+}
+
+static void fill_tex2d_srv_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0;
+ UINT array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MostDetailedMip = mip_slice;
+ desc->Texture2DArray.MipLevels = 1;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+}
+
+static void fill_tex2d_uav_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0;
+ UINT array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MipSlice = mip_slice;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+ return ff_d3d11_ensure_texture(ctx, s->device, tex, cur_w, cur_h, cur_fmt,
+ w, h, fmt, bind_flags, "D3D11 overlay");
+}
+
+static int create_nv12_uav_view(AVFilterContext *ctx, ID3D11Texture2D *tex,
@@ -401,20 +272,10 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ ID3D11UnorderedAccessView **uav)
+{
+ OverlayD3D11Context *s = ctx->priv;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ fill_tex2d_uav_desc(tex, subresource, plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM, &desc);
+
+ hr = s->device->lpVtbl->CreateUnorderedAccessView(s->device,
+ (ID3D11Resource *)tex,
+ &desc, uav);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating NV12 plane %d UAV: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_uav(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(AV_PIX_FMT_NV12, plane),
+ log_level, "D3D11 overlay", uav);
+}
+
+static int create_nv12_uav(AVFilterContext *ctx, ID3D11Texture2D *tex, int plane,
@@ -429,22 +290,12 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ ID3D11ShaderResourceView **srv)
+{
+ OverlayD3D11Context *s = ctx->priv;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ if (plane >= 0)
+ fmt = plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM;
+ fill_tex2d_srv_desc(tex, subresource, fmt, &desc);
+ fmt = ff_d3d11_plane_format(AV_PIX_FMT_NV12, plane);
+
+ hr = s->device->lpVtbl->CreateShaderResourceView(s->device,
+ (ID3D11Resource *)tex,
+ &desc, srv);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating overlay SRV: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_srv(ctx, s->device, tex, subresource, fmt,
+ log_level, "D3D11 overlay", srv);
+}
+
+static int create_srv(AVFilterContext *ctx, ID3D11Texture2D *tex, DXGI_FORMAT fmt,
@@ -453,39 +304,6 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ return create_srv_view(ctx, tex, 0, fmt, plane, AV_LOG_ERROR, srv);
+}
+
+static void copy_frame_to_texture(OverlayD3D11Context *s, AVFrame *src, ID3D11Texture2D *dst)
+{
+ ID3D11Texture2D *src_tex = (ID3D11Texture2D *)src->data[0];
+ UINT src_sub = (UINT)(uintptr_t)src->data[1];
+ D3D11_BOX box = { 0, 0, 0, src->width, src->height, 1 };
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst, 0,
+ 0, 0, 0, (ID3D11Resource *)src_tex,
+ src_sub, &box);
+}
+
+static void copy_texture_to_frame(OverlayD3D11Context *s, ID3D11Texture2D *src, AVFrame *dst)
+{
+ ID3D11Texture2D *dst_tex = (ID3D11Texture2D *)dst->data[0];
+ UINT dst_sub = (UINT)(uintptr_t)dst->data[1];
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst_tex,
+ dst_sub, 0, 0, 0, (ID3D11Resource *)src,
+ 0, NULL);
+}
+
+static void copy_frame_to_frame(OverlayD3D11Context *s, AVFrame *src, AVFrame *dst)
+{
+ ID3D11Texture2D *src_tex = (ID3D11Texture2D *)src->data[0];
+ ID3D11Texture2D *dst_tex = (ID3D11Texture2D *)dst->data[0];
+ UINT src_sub = (UINT)(uintptr_t)src->data[1];
+ UINT dst_sub = (UINT)(uintptr_t)dst->data[1];
+ D3D11_BOX box = { 0, 0, 0, src->width, src->height, 1 };
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst_tex,
+ dst_sub, 0, 0, 0, (ID3D11Resource *)src_tex,
+ src_sub, &box);
+}
+
+static int create_overlay_frame_srvs(AVFilterContext *ctx, AVFrame *overlay,
+ ID3D11ShaderResourceView **srvs)
+{
@@ -510,7 +328,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ ret = create_srv_view(ctx, tex, subresource, DXGI_FORMAT_NV12, 1,
+ AV_LOG_DEBUG, &srvs[2]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(srvs[1]);
+ return ret;
+}
+
@@ -539,14 +357,14 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ D3D11_BIND_SHADER_RESOURCE);
+ if (ret < 0)
+ return ret;
+ copy_frame_to_texture(s, main, s->main_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, main, s->main_tex);
+
+ ret = create_srv(ctx, s->main_tex, DXGI_FORMAT_NV12, 0, &srvs[1]);
+ if (ret < 0)
+ return ret;
+ ret = create_srv(ctx, s->main_tex, DXGI_FORMAT_NV12, 1, &srvs[2]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(srvs[1]);
+ return ret;
+}
+
@@ -575,7 +393,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_SHADER_RESOURCE);
+ if (ret < 0)
+ return ret;
+ copy_frame_to_texture(s, overlay, s->overlay_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, overlay, s->overlay_tex);
+
+ return create_srv(ctx, s->overlay_tex, DXGI_FORMAT_B8G8R8A8_UNORM, -1, &srvs[0]);
+}
@@ -601,8 +419,8 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ *direct = 1;
+ return 0;
+ }
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ if (s->direct_output_uav < 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: copied from internal UAV texture\n");
+ s->direct_output_uav = 0;
@@ -618,7 +436,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ return ret;
+ ret = create_nv12_uav(ctx, s->work_tex, 1, &uavs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[0]);
+ return ret;
+}
+
@@ -653,8 +471,8 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ ret = create_nv12_uav_view(ctx, tex, subresource, 1, AV_LOG_DEBUG, &uavs[1]);
+
+done:
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&frame);
+ return ret;
+}
@@ -702,7 +520,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ out->format = AV_PIX_FMT_D3D11;
+
+ if (!overlay) {
+ copy_frame_to_frame(s, main, out);
+ ff_d3d11_copy_frame_to_frame(s->context, main, out);
+ av_frame_free(&main);
+ return ff_filter_frame(outlink, out);
+ }
@@ -761,13 +579,13 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+
+ if (!direct_output)
+ copy_texture_to_frame(s, s->work_tex, out);
+ ff_d3d11_copy_texture_to_frame(s->context, s->work_tex, out);
+
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ D3D11_RELEASE(srvs[0]);
+ D3D11_RELEASE(srvs[1]);
+ D3D11_RELEASE(srvs[2]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(srvs[2]);
+ av_frame_free(&main);
+
+ return ff_filter_frame(outlink, out);
@@ -777,11 +595,11 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ s->context->lpVtbl->CSSetUnorderedAccessViews(s->context, 0, 2, null_uavs, NULL);
+ s->context->lpVtbl->CSSetShaderResources(s->context, 0, 3, null_srvs);
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ D3D11_RELEASE(srvs[0]);
+ D3D11_RELEASE(srvs[1]);
+ D3D11_RELEASE(srvs[2]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(srvs[2]);
+ av_frame_free(&main);
+ av_frame_free(&out);
+ return ret;
@@ -975,8 +793,7 @@ Index: FFmpeg/libavfilter/vf_overlay_d3d11.c
+ overlay_d3d11_release_resources(s);
+ av_buffer_unref(&s->hw_frames_ctx_out);
+ av_buffer_unref(&s->hw_device_ctx);
+ if (s->d3dcompiler)
+ FreeLibrary(s->d3dcompiler);
+ ff_d3d11_unload_shader_compiler(&s->d3dcompiler, &s->D3DCompile);
+ av_freep(&s->overlay_ox);
+ av_freep(&s->overlay_oy);
+ av_freep(&s->overlay_ow);
+41 -214
View File
@@ -18,7 +18,7 @@ Index: FFmpeg/libavfilter/Makefile
OBJS-$(CONFIG_TONEMAPX_FILTER) += vf_tonemapx.o
OBJS-$(CONFIG_TONEMAP_CUDA_FILTER) += vf_tonemap_cuda.o cuda/tonemap.ptx.o \
cuda/host_util.o cuda/load_helper.o
+OBJS-$(CONFIG_TONEMAP_D3D11_FILTER) += vf_tonemap_d3d11.o d3d11/tonemap.o
+OBJS-$(CONFIG_TONEMAP_D3D11_FILTER) += vf_tonemap_d3d11.o d3d11/tonemap.o d3d11_filter.o
OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o opencl.o \
opencl/tonemap.o opencl/colorspace_common.o
OBJS-$(CONFIG_TONEMAP_VAAPI_FILTER) += vf_tonemap_vaapi.o vaapi_vpp.o
@@ -38,7 +38,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/vf_tonemap_d3d11.c
@@ -0,0 +1,1267 @@
@@ -0,0 +1,1094 @@
+/*
+ * D3D11 tonemap filter
+ *
@@ -69,7 +69,6 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+#define COBJMACROS
+#endif
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mathematics.h"
@@ -87,12 +86,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+#include "video.h"
+#include "vf_tonemap_d3d11.h"
+#include "d3d11_source.h"
+#include "d3d11_filter.h"
+
+#define REF_WHITE_SCALE (REFERENCE_WHITE / REFERENCE_WHITE_ALT)
+#define D3D11_RELEASE(p) do { if (p) { (p)->lpVtbl->Release(p); (p) = NULL; } } while (0)
+#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
+#endif
+
+enum TonemapAlgorithm {
+ TONEMAP_NONE,
@@ -115,11 +111,6 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ TONEMAP_MODE_COUNT,
+};
+
+typedef HRESULT (WINAPI *D3DCompileProc)(LPCVOID, SIZE_T, LPCSTR,
+ const D3D_SHADER_MACRO *, ID3DInclude *,
+ LPCSTR, LPCSTR, UINT, UINT,
+ ID3D10Blob **, ID3D10Blob **);
+
+typedef struct TonemapD3D11Params {
+ int width;
+ int height;
@@ -189,7 +180,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ ID3D11Device *device;
+ ID3D11DeviceContext *context;
+ HMODULE d3dcompiler;
+ D3DCompileProc D3DCompile;
+ FFD3DCompileProc D3DCompile;
+ ID3D11ComputeShader *cs;
+ ID3D11Buffer *params_buf;
+ ID3D11Texture2D *src_tex;
@@ -242,28 +233,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ return fmt == AV_PIX_FMT_NV12 || fmt == AV_PIX_FMT_P010 || fmt == AV_PIX_FMT_P016;
+}
+
+static DXGI_FORMAT texture_format(enum AVPixelFormat fmt)
+{
+ if (fmt == AV_PIX_FMT_P010)
+ return DXGI_FORMAT_P010;
+ if (fmt == AV_PIX_FMT_P016)
+ return DXGI_FORMAT_P016;
+ return DXGI_FORMAT_NV12;
+}
+
+static DXGI_FORMAT plane_format(enum AVPixelFormat fmt, int plane)
+{
+ if (fmt == AV_PIX_FMT_NV12)
+ return plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM;
+ return plane ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R16_UNORM;
+}
+
+static void release_d3d11_resources(TonemapD3D11Context *s)
+{
+ D3D11_RELEASE(s->cs);
+ D3D11_RELEASE(s->params_buf);
+ D3D11_RELEASE(s->src_tex);
+ D3D11_RELEASE(s->work_tex);
+ FF_D3D11_RELEASE(s->cs);
+ FF_D3D11_RELEASE(s->params_buf);
+ FF_D3D11_RELEASE(s->src_tex);
+ FF_D3D11_RELEASE(s->work_tex);
+ s->shader_tonemap = s->shader_mode = s->shader_trc_in = s->shader_trc_out = -1;
+ s->shader_full_in = s->shader_full_out = s->shader_out_depth = s->shader_skip = s->shader_dovi = -1;
+ s->src_w = s->src_h = 0;
@@ -281,8 +256,6 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ int skip, int dovi)
+{
+ TonemapD3D11Context *s = ctx->priv;
+ ID3D10Blob *cs_blob = NULL;
+ ID3D10Blob *err_blob = NULL;
+ char tonemap_buf[16], mode_buf[16], trc_in_buf[16], trc_out_buf[16];
+ char full_in_buf[16], full_out_buf[16], out_depth_buf[16], skip_buf[16], dovi_buf[16];
+ D3D_SHADER_MACRO macros[] = {
@@ -297,7 +270,6 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ { "APPLY_DOVI_VAL", dovi_buf },
+ { NULL, NULL },
+ };
+ HRESULT hr;
+
+ macro_int(tonemap_buf, sizeof(tonemap_buf), tonemap);
+ macro_int(mode_buf, sizeof(mode_buf), mode);
@@ -309,34 +281,11 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ macro_int(skip_buf, sizeof(skip_buf), skip);
+ macro_int(dovi_buf, sizeof(dovi_buf), dovi);
+
+ D3D11_RELEASE(s->cs);
+ hr = s->D3DCompile(ff_source_tonemap_hlsl, strlen(ff_source_tonemap_hlsl),
+ NULL, macros, NULL, "tonemap_main", "cs_5_0",
+ D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &cs_blob, &err_blob);
+ if (FAILED(hr)) {
+ if (err_blob) {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 tonemap shader: %.*s\n",
+ (int)err_blob->lpVtbl->GetBufferSize(err_blob),
+ (char *)err_blob->lpVtbl->GetBufferPointer(err_blob));
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 tonemap shader: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ }
+ D3D11_RELEASE(err_blob);
+ FF_D3D11_RELEASE(s->cs);
+ if (ff_d3d11_compile_shader(ctx, s->device, s->D3DCompile,
+ ff_source_tonemap_hlsl, macros, "tonemap_main",
+ "cs_5_0", "D3D11 tonemap", &s->cs) < 0)
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = s->device->lpVtbl->CreateComputeShader(s->device,
+ cs_blob->lpVtbl->GetBufferPointer(cs_blob),
+ cs_blob->lpVtbl->GetBufferSize(cs_blob),
+ NULL, &s->cs);
+ D3D11_RELEASE(cs_blob);
+ D3D11_RELEASE(err_blob);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 tonemap shader: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ s->shader_tonemap = tonemap;
+ s->shader_mode = mode;
@@ -353,39 +302,17 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+static int ensure_compiler_and_params(AVFilterContext *ctx)
+{
+ TonemapD3D11Context *s = ctx->priv;
+ D3D11_BUFFER_DESC bd = { 0 };
+ HRESULT hr;
+ int ret;
+
+ if (!s->d3dcompiler) {
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_47.dll");
+ if (!s->d3dcompiler)
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_43.dll");
+ }
+ if (!s->d3dcompiler) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading d3dcompiler DLL\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ s->D3DCompile = (D3DCompileProc)GetProcAddress(s->d3dcompiler, "D3DCompile");
+ if (!s->D3DCompile) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading D3DCompile\n");
+ return AVERROR_EXTERNAL;
+ }
+ ret = ff_d3d11_load_shader_compiler(ctx, &s->d3dcompiler, &s->D3DCompile);
+ if (ret < 0)
+ return ret;
+
+ if (s->params_buf)
+ return 0;
+
+ bd.ByteWidth = sizeof(TonemapD3D11Params);
+ bd.Usage = D3D11_USAGE_DYNAMIC;
+ bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ hr = s->device->lpVtbl->CreateBuffer(s->device, &bd, NULL, &s->params_buf);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 tonemap constant buffer: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_const_buffer(ctx, s->device, sizeof(TonemapD3D11Params),
+ "D3D11 tonemap", &s->params_buf);
+}
+
+static int ensure_shader_variant(AVFilterContext *ctx, const TonemapD3D11Params *params)
@@ -421,70 +348,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ enum AVPixelFormat fmt, UINT bind_flags)
+{
+ TonemapD3D11Context *s = ctx->priv;
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ HRESULT hr;
+
+ if (*tex && *cur_w == w && *cur_h == h)
+ return 0;
+
+ D3D11_RELEASE(*tex);
+ desc.Width = w;
+ desc.Height = h;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = texture_format(fmt);
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bind_flags;
+
+ hr = s->device->lpVtbl->CreateTexture2D(s->device, &desc, NULL, tex);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 tonemap texture: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ *cur_w = w;
+ *cur_h = h;
+ return 0;
+}
+
+static void fill_tex2d_srv_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0, array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MostDetailedMip = mip_slice;
+ desc->Texture2DArray.MipLevels = 1;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+}
+
+static void fill_tex2d_uav_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0, array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MipSlice = mip_slice;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+ return ff_d3d11_ensure_texture(ctx, s->device, tex, cur_w, cur_h, NULL,
+ w, h, ff_d3d11_texture_format(fmt), bind_flags,
+ "D3D11 tonemap");
+}
+
+static int create_srv_view(AVFilterContext *ctx, ID3D11Texture2D *tex,
@@ -492,18 +359,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ int log_level, ID3D11ShaderResourceView **srv)
+{
+ TonemapD3D11Context *s = ctx->priv;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ fill_tex2d_srv_desc(tex, subresource, plane_format(fmt, plane), &desc);
+ hr = s->device->lpVtbl->CreateShaderResourceView(s->device, (ID3D11Resource *)tex,
+ &desc, srv);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 tonemap SRV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_srv(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(fmt, plane),
+ log_level, "D3D11 tonemap", srv);
+}
+
+static int create_uav_view(AVFilterContext *ctx, ID3D11Texture2D *tex,
@@ -511,39 +370,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ int log_level, ID3D11UnorderedAccessView **uav)
+{
+ TonemapD3D11Context *s = ctx->priv;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ fill_tex2d_uav_desc(tex, subresource, plane_format(fmt, plane), &desc);
+ hr = s->device->lpVtbl->CreateUnorderedAccessView(s->device, (ID3D11Resource *)tex,
+ &desc, uav);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 tonemap UAV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+}
+
+static void copy_frame_to_texture(TonemapD3D11Context *s, AVFrame *src, ID3D11Texture2D *dst)
+{
+ ID3D11Texture2D *src_tex = (ID3D11Texture2D *)src->data[0];
+ UINT src_sub = (UINT)(uintptr_t)src->data[1];
+ D3D11_BOX box = { 0, 0, 0, src->width, src->height, 1 };
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst, 0,
+ 0, 0, 0, (ID3D11Resource *)src_tex,
+ src_sub, &box);
+}
+
+static void copy_texture_to_frame(TonemapD3D11Context *s, ID3D11Texture2D *src, AVFrame *dst)
+{
+ ID3D11Texture2D *dst_tex = (ID3D11Texture2D *)dst->data[0];
+ UINT dst_sub = (UINT)(uintptr_t)dst->data[1];
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst_tex,
+ dst_sub, 0, 0, 0, (ID3D11Resource *)src,
+ 0, NULL);
+ return ff_d3d11_create_uav(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(fmt, plane),
+ log_level, "D3D11 tonemap", uav);
+}
+
+static int create_frame_srvs(AVFilterContext *ctx, AVFrame *frame,
@@ -559,7 +389,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ return ret;
+ ret = create_srv_view(ctx, tex, subresource, s->in_fmt, 1, AV_LOG_DEBUG, &srvs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[0]);
+ return ret;
+}
+
@@ -589,13 +419,13 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ D3D11_BIND_SHADER_RESOURCE);
+ if (ret < 0)
+ return ret;
+ copy_frame_to_texture(s, input, s->src_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, input, s->src_tex);
+ ret = create_srv_view(ctx, s->src_tex, 0, s->in_fmt, 0, AV_LOG_ERROR, &srvs[0]);
+ if (ret < 0)
+ return ret;
+ ret = create_srv_view(ctx, s->src_tex, 0, s->in_fmt, 1, AV_LOG_ERROR, &srvs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[0]);
+ return ret;
+}
+
@@ -620,8 +450,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ *direct = 1;
+ return 0;
+ }
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ if (s->direct_output_uav < 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: copied from internal UAV texture\n");
+ s->direct_output_uav = 0;
@@ -637,7 +467,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ return ret;
+ ret = create_uav_view(ctx, s->work_tex, 0, s->out_fmt, 1, AV_LOG_ERROR, &uavs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[0]);
+ return ret;
+}
+
@@ -671,8 +501,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ ret = create_uav_view(ctx, tex, subresource, s->out_fmt, 1, AV_LOG_DEBUG, &uavs[1]);
+
+done:
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&frame);
+ return ret;
+}
@@ -881,17 +711,17 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+
+ if (!direct_output)
+ copy_texture_to_frame(s, s->work_tex, output);
+ ff_d3d11_copy_texture_to_frame(s->context, s->work_tex, output);
+
+fail:
+ s->context->lpVtbl->CSSetShader(s->context, NULL, NULL, 0);
+ s->context->lpVtbl->CSSetShaderResources(s->context, 0, 2, null_srvs);
+ s->context->lpVtbl->CSSetUnorderedAccessViews(s->context, 0, 2, null_uavs, NULL);
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+ D3D11_RELEASE(srvs[0]);
+ D3D11_RELEASE(srvs[1]);
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ return ret;
+}
+
@@ -1180,10 +1010,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_d3d11.c
+ release_d3d11_resources(s);
+ av_buffer_unref(&s->hw_device_ctx);
+ av_buffer_unref(&s->hw_frames_ctx_out);
+ if (s->d3dcompiler) {
+ FreeLibrary(s->d3dcompiler);
+ s->d3dcompiler = NULL;
+ }
+ ff_d3d11_unload_shader_compiler(&s->d3dcompiler, &s->D3DCompile);
+}
+
+static int tonemap_d3d11_query_formats(AVFilterContext *avctx)
+59 -231
View File
@@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
===================================================================
--- FFmpeg.orig/libavfilter/vf_scale_d3d11.c
+++ FFmpeg/libavfilter/vf_scale_d3d11.c
@@ -21,7 +21,15 @@
@@ -21,7 +21,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -11,31 +11,21 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+#define COBJMACROS
+#endif
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
#include "libavutil/opt.h"
+#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "compat/w32dlfcn.h"
@@ -31,6 +39,26 @@
@@ -31,6 +38,17 @@
#include "filters.h"
#include "scale_eval.h"
#include "video.h"
+#include "d3d11_source.h"
+#include "d3d11_filter.h"
+
+#define SCALE_D3D11_TGX 16
+#define SCALE_D3D11_TGY 16
+#define D3D11_RELEASE(p) do { if (p) { (p)->lpVtbl->Release(p); (p) = NULL; } } while (0)
+#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
+#endif
+
+typedef HRESULT (WINAPI *D3DCompileProc)(LPCVOID, SIZE_T, LPCSTR,
+ const D3D_SHADER_MACRO *, ID3DInclude *,
+ LPCSTR, LPCSTR, UINT, UINT,
+ ID3D10Blob **, ID3D10Blob **);
+
+typedef struct ScaleD3D11Params {
+ int src_w;
+ int src_h;
@@ -45,12 +35,12 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
typedef struct ScaleD3D11Context {
const AVClass *classCtx;
@@ -47,12 +75,27 @@ typedef struct ScaleD3D11Context {
@@ -47,12 +65,27 @@ typedef struct ScaleD3D11Context {
ID3D11VideoProcessorOutputView *outputView;
ID3D11VideoProcessorInputView *inputView;
+ HMODULE d3dcompiler;
+ D3DCompileProc D3DCompile;
+ FFD3DCompileProc D3DCompile;
+ ID3D11ComputeShader *cs_y;
+ ID3D11ComputeShader *cs_uv;
+ ID3D11Buffer *params_buf;
@@ -73,105 +63,44 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
int inputWidth, inputHeight;
DXGI_FORMAT input_format;
DXGI_FORMAT output_format;
@@ -83,6 +126,340 @@ static void release_d3d11_resources(Scal
@@ -83,6 +116,181 @@ static void release_d3d11_resources(Scal
s->videoDevice->lpVtbl->Release(s->videoDevice);
s->videoDevice = NULL;
}
+
+ D3D11_RELEASE(s->cs_y);
+ D3D11_RELEASE(s->cs_uv);
+ D3D11_RELEASE(s->params_buf);
+ D3D11_RELEASE(s->src_tex);
+ D3D11_RELEASE(s->work_tex);
+ FF_D3D11_RELEASE(s->cs_y);
+ FF_D3D11_RELEASE(s->cs_uv);
+ FF_D3D11_RELEASE(s->params_buf);
+ FF_D3D11_RELEASE(s->src_tex);
+ FF_D3D11_RELEASE(s->work_tex);
+ s->src_tex_w = s->src_tex_h = 0;
+ s->work_w = s->work_h = 0;
+}
+
+static DXGI_FORMAT scale_d3d11_texture_format(enum AVPixelFormat fmt)
+{
+ return fmt == AV_PIX_FMT_P010 ? DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
+}
+
+static DXGI_FORMAT scale_d3d11_plane_format(enum AVPixelFormat fmt, int plane)
+{
+ if (fmt == AV_PIX_FMT_NV12)
+ return plane ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R8_UNORM;
+ return plane ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R16_UNORM;
+}
+
+static int scale_d3d11_compile_shader(AVFilterContext *ctx, const char *entry,
+ ID3D11ComputeShader **shader)
+{
+ ScaleD3D11Context *s = ctx->priv;
+ ID3D10Blob *cs_blob = NULL;
+ ID3D10Blob *err_blob = NULL;
+ HRESULT hr;
+
+ hr = s->D3DCompile(ff_source_scale_hlsl, strlen(ff_source_scale_hlsl),
+ NULL, NULL, NULL, entry, "cs_5_0",
+ D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &cs_blob, &err_blob);
+ if (FAILED(hr)) {
+ if (err_blob) {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 scale shader %s: %.*s\n",
+ entry, (int)err_blob->lpVtbl->GetBufferSize(err_blob),
+ (char *)err_blob->lpVtbl->GetBufferPointer(err_blob));
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "Failed compiling D3D11 scale shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ }
+ D3D11_RELEASE(err_blob);
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = s->device->lpVtbl->CreateComputeShader(s->device,
+ cs_blob->lpVtbl->GetBufferPointer(cs_blob),
+ cs_blob->lpVtbl->GetBufferSize(cs_blob),
+ NULL, shader);
+ D3D11_RELEASE(cs_blob);
+ D3D11_RELEASE(err_blob);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 scale shader %s: HRESULT 0x%lX\n",
+ entry, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+ return ff_d3d11_compile_shader(ctx, s->device, s->D3DCompile,
+ ff_source_scale_hlsl, NULL, entry,
+ "cs_5_0", "D3D11 scale", shader);
+}
+
+static int scale_d3d11_ensure_shader(AVFilterContext *ctx)
+{
+ ScaleD3D11Context *s = ctx->priv;
+ D3D11_BUFFER_DESC bd = { 0 };
+ HRESULT hr;
+ int ret;
+
+ if (!s->d3dcompiler) {
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_47.dll");
+ if (!s->d3dcompiler)
+ s->d3dcompiler = LoadLibraryA("d3dcompiler_43.dll");
+ }
+ if (!s->d3dcompiler) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading d3dcompiler DLL\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ s->D3DCompile = (D3DCompileProc)GetProcAddress(s->d3dcompiler, "D3DCompile");
+ if (!s->D3DCompile) {
+ av_log(ctx, AV_LOG_ERROR, "Failed loading D3DCompile\n");
+ return AVERROR_EXTERNAL;
+ }
+ ret = ff_d3d11_load_shader_compiler(ctx, &s->d3dcompiler, &s->D3DCompile);
+ if (ret < 0)
+ return ret;
+
+ if (!s->params_buf) {
+ bd.ByteWidth = sizeof(ScaleD3D11Params);
+ bd.Usage = D3D11_USAGE_DYNAMIC;
+ bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ hr = s->device->lpVtbl->CreateBuffer(s->device, &bd, NULL, &s->params_buf);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 scale constant buffer: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ ret = ff_d3d11_create_const_buffer(ctx, s->device, sizeof(ScaleD3D11Params),
+ "D3D11 scale", &s->params_buf);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!s->cs_y) {
@@ -193,71 +122,10 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ enum AVPixelFormat fmt, UINT bind_flags)
+{
+ ScaleD3D11Context *s = ctx->priv;
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ HRESULT hr;
+
+ if (*tex && *cur_w == w && *cur_h == h)
+ return 0;
+
+ D3D11_RELEASE(*tex);
+ desc.Width = w;
+ desc.Height = h;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = scale_d3d11_texture_format(fmt);
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bind_flags;
+
+ hr = s->device->lpVtbl->CreateTexture2D(s->device, &desc, NULL, tex);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed creating D3D11 scale texture: HRESULT 0x%lX\n",
+ (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ *cur_w = w;
+ *cur_h = h;
+ return 0;
+}
+
+static void scale_d3d11_fill_srv_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0, array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MostDetailedMip = mip_slice;
+ desc->Texture2DArray.MipLevels = 1;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+}
+
+static void scale_d3d11_fill_uav_desc(ID3D11Texture2D *tex, UINT subresource,
+ DXGI_FORMAT fmt, D3D11_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ D3D11_TEXTURE2D_DESC tex_desc;
+ UINT mip_slice = 0, array_slice = 0;
+
+ ID3D11Texture2D_GetDesc(tex, &tex_desc);
+ if (tex_desc.MipLevels) {
+ mip_slice = subresource % tex_desc.MipLevels;
+ array_slice = subresource / tex_desc.MipLevels;
+ }
+
+ desc->Format = fmt;
+ desc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ desc->Texture2DArray.MipSlice = mip_slice;
+ desc->Texture2DArray.FirstArraySlice = array_slice;
+ desc->Texture2DArray.ArraySize = 1;
+ return ff_d3d11_ensure_texture(ctx, s->device, tex, cur_w, cur_h, NULL,
+ w, h, ff_d3d11_texture_format(fmt), bind_flags,
+ "D3D11 scale");
+}
+
+static int scale_d3d11_create_srv(AVFilterContext *ctx, ID3D11Texture2D *tex,
@@ -265,18 +133,10 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ int log_level, ID3D11ShaderResourceView **srv)
+{
+ ScaleD3D11Context *s = ctx->priv;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ scale_d3d11_fill_srv_desc(tex, subresource, scale_d3d11_plane_format(fmt, plane), &desc);
+ hr = s->device->lpVtbl->CreateShaderResourceView(s->device, (ID3D11Resource *)tex,
+ &desc, srv);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 scale SRV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+ return ff_d3d11_create_srv(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(fmt, plane),
+ log_level, "D3D11 scale", srv);
+}
+
+static int scale_d3d11_create_uav(AVFilterContext *ctx, ID3D11Texture2D *tex,
@@ -284,39 +144,10 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ int log_level, ID3D11UnorderedAccessView **uav)
+{
+ ScaleD3D11Context *s = ctx->priv;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = { 0 };
+ HRESULT hr;
+
+ scale_d3d11_fill_uav_desc(tex, subresource, scale_d3d11_plane_format(fmt, plane), &desc);
+ hr = s->device->lpVtbl->CreateUnorderedAccessView(s->device, (ID3D11Resource *)tex,
+ &desc, uav);
+ if (FAILED(hr)) {
+ av_log(ctx, log_level, "Failed creating D3D11 scale UAV plane %d: HRESULT 0x%lX\n",
+ plane, (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+ return 0;
+}
+
+static void scale_d3d11_copy_frame_to_texture(ScaleD3D11Context *s, AVFrame *src, ID3D11Texture2D *dst)
+{
+ ID3D11Texture2D *src_tex = (ID3D11Texture2D *)src->data[0];
+ UINT src_sub = (UINT)(uintptr_t)src->data[1];
+ D3D11_BOX box = { 0, 0, 0, src->width, src->height, 1 };
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst, 0,
+ 0, 0, 0, (ID3D11Resource *)src_tex,
+ src_sub, &box);
+}
+
+static void scale_d3d11_copy_texture_to_frame(ScaleD3D11Context *s, ID3D11Texture2D *src, AVFrame *dst)
+{
+ ID3D11Texture2D *dst_tex = (ID3D11Texture2D *)dst->data[0];
+ UINT dst_sub = (UINT)(uintptr_t)dst->data[1];
+
+ s->context->lpVtbl->CopySubresourceRegion(s->context, (ID3D11Resource *)dst_tex,
+ dst_sub, 0, 0, 0, (ID3D11Resource *)src,
+ 0, NULL);
+ return ff_d3d11_create_uav(ctx, s->device, tex, subresource,
+ ff_d3d11_plane_format(fmt, plane),
+ log_level, "D3D11 scale", uav);
+}
+
+static int scale_d3d11_create_frame_srvs(AVFilterContext *ctx, AVFrame *frame,
@@ -332,7 +163,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ return ret;
+ ret = scale_d3d11_create_srv(ctx, tex, subresource, s->in_format, 1, AV_LOG_DEBUG, &srvs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[0]);
+ return ret;
+}
+
@@ -361,13 +192,13 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ D3D11_BIND_SHADER_RESOURCE);
+ if (ret < 0)
+ return ret;
+ scale_d3d11_copy_frame_to_texture(s, input, s->src_tex);
+ ff_d3d11_copy_frame_to_texture(s->context, input, s->src_tex);
+ ret = scale_d3d11_create_srv(ctx, s->src_tex, 0, s->in_format, 0, AV_LOG_ERROR, &srvs[0]);
+ if (ret < 0)
+ return ret;
+ ret = scale_d3d11_create_srv(ctx, s->src_tex, 0, s->in_format, 1, AV_LOG_ERROR, &srvs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[0]);
+ return ret;
+}
+
@@ -392,8 +223,8 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ *direct = 1;
+ return 0;
+ }
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ if (s->direct_output_uav < 0)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: copied from internal UAV texture\n");
+ s->direct_output_uav = 0;
@@ -409,12 +240,12 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ return ret;
+ ret = scale_d3d11_create_uav(ctx, s->work_tex, 0, s->format, 1, AV_LOG_ERROR, &uavs[1]);
+ if (ret < 0)
+ D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[0]);
+ return ret;
}
static int scale_d3d11_configure_processor(ScaleD3D11Context *s, AVFilterContext *ctx) {
@@ -144,6 +521,152 @@ static int scale_d3d11_configure_process
@@ -144,6 +352,152 @@ static int scale_d3d11_configure_process
return 0;
}
@@ -448,8 +279,8 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ ret = scale_d3d11_create_uav(ctx, tex, subresource, s->format, 1, AV_LOG_DEBUG, &uavs[1]);
+
+done:
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&frame);
+ return ret;
+}
@@ -541,12 +372,12 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+
+ if (!direct_output)
+ scale_d3d11_copy_texture_to_frame(s, s->work_tex, out);
+ ff_d3d11_copy_texture_to_frame(s->context, s->work_tex, out);
+
+ D3D11_RELEASE(srvs[0]);
+ D3D11_RELEASE(srvs[1]);
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&in);
+ return ff_filter_frame(outlink, out);
+
@@ -555,10 +386,10 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ s->context->lpVtbl->CSSetShaderResources(s->context, 0, 2, null_srvs);
+ s->context->lpVtbl->CSSetUnorderedAccessViews(s->context, 0, 2, null_uavs, NULL);
+ s->context->lpVtbl->CSSetConstantBuffers(s->context, 0, 1, null_cb);
+ D3D11_RELEASE(srvs[0]);
+ D3D11_RELEASE(srvs[1]);
+ D3D11_RELEASE(uavs[0]);
+ D3D11_RELEASE(uavs[1]);
+ FF_D3D11_RELEASE(srvs[0]);
+ FF_D3D11_RELEASE(srvs[1]);
+ FF_D3D11_RELEASE(uavs[0]);
+ FF_D3D11_RELEASE(uavs[1]);
+ av_frame_free(&in);
+ av_frame_free(&out);
+ return ret;
@@ -567,7 +398,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
static int scale_d3d11_filter_frame(AVFilterLink *inlink, AVFrame *in)
{
AVFilterContext *ctx = inlink->dst;
@@ -185,6 +708,9 @@ static int scale_d3d11_filter_frame(AVFi
@@ -185,6 +539,9 @@ static int scale_d3d11_filter_frame(AVFi
return AVERROR(EINVAL);
}
@@ -577,7 +408,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Allocate output frame
out = av_frame_alloc();
if (!out) {
@@ -353,13 +879,6 @@ static int scale_d3d11_config_props(AVFi
@@ -353,13 +710,6 @@ static int scale_d3d11_config_props(AVFi
return AVERROR(EINVAL);
}
@@ -591,7 +422,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Initialize filter's hardware device context
if (!s->hw_device_ctx) {
AVHWFramesContext *in_frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data;
@@ -382,6 +901,29 @@ static int scale_d3d11_config_props(AVFi
@@ -382,6 +732,29 @@ static int scale_d3d11_config_props(AVFi
return AVERROR(EINVAL);
}
@@ -621,7 +452,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
///< Create new hardware frames context for output
s->hw_frames_ctx_out = av_hwframe_ctx_alloc(s->hw_device_ctx);
if (!s->hw_frames_ctx_out)
@@ -399,16 +941,43 @@ static int scale_d3d11_config_props(AVFi
@@ -399,16 +772,43 @@ static int scale_d3d11_config_props(AVFi
AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
frames_hwctx->MiscFlags = 0;
@@ -654,7 +485,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ } else if (s->shader_fallback) {
+ s->direct_output_uav = 0;
+ }
+
+
+ if (s->shader_fallback) {
+ av_log(ctx, AV_LOG_VERBOSE, "D3D11 scale: using P010 output path\n");
@@ -663,24 +494,21 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
+ else if (s->force_output_copy)
+ av_log(ctx, AV_LOG_DEBUG, "D3D11 shader output: forced copy from internal UAV texture\n");
+ }
+
+ av_buffer_unref(&outl->hw_frames_ctx);
outl->hw_frames_ctx = av_buffer_ref(s->hw_frames_ctx_out);
if (!outl->hw_frames_ctx)
return AVERROR(ENOMEM);
@@ -424,6 +993,11 @@ static av_cold void scale_d3d11_uninit(A
@@ -424,6 +824,8 @@ static av_cold void scale_d3d11_uninit(A
///< Release D3D11 resources
release_d3d11_resources(s);
+ if (s->d3dcompiler) {
+ FreeLibrary(s->d3dcompiler);
+ s->d3dcompiler = NULL;
+ }
+ ff_d3d11_unload_shader_compiler(&s->d3dcompiler, &s->D3DCompile);
+
///< Free the hardware device context reference
av_buffer_unref(&s->hw_frames_ctx_out);
av_buffer_unref(&s->hw_device_ctx);
@@ -453,9 +1027,12 @@ static const AVFilterPad scale_d3d11_out
@@ -453,9 +855,12 @@ static const AVFilterPad scale_d3d11_out
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
static const AVOption scale_d3d11_options[] = {
@@ -693,7 +521,7 @@ Index: FFmpeg/libavfilter/vf_scale_d3d11.c
{ NULL }
};
@@ -463,7 +1040,7 @@ AVFILTER_DEFINE_CLASS(scale_d3d11);
@@ -463,7 +868,7 @@ AVFILTER_DEFINE_CLASS(scale_d3d11);
const FFFilter ff_vf_scale_d3d11 = {
.p.name = "scale_d3d11",
@@ -711,7 +539,7 @@ Index: FFmpeg/libavfilter/Makefile
OBJS-$(CONFIG_SAB_FILTER) += vf_sab.o
OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale_eval.o framesync.o
-OBJS-$(CONFIG_SCALE_D3D11_FILTER) += vf_scale_d3d11.o scale_eval.o
+OBJS-$(CONFIG_SCALE_D3D11_FILTER) += vf_scale_d3d11.o scale_eval.o d3d11/scale.o
+OBJS-$(CONFIG_SCALE_D3D11_FILTER) += vf_scale_d3d11.o scale_eval.o d3d11/scale.o d3d11_filter.o
OBJS-$(CONFIG_SCALE_D3D12_FILTER) += vf_scale_d3d12.o scale_eval.o
OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \
vf_scale_cuda.ptx.o cuda/load_helper.o