[vlc-commits] [Git][videolan/vlc][3.0.x] 13 commits: d3d11_fmt: allow build D3D11 modules with C++
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Wed Apr 26 16:12:37 UTC 2023
Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC
Commits:
371c0787 by Steve Lhomme at 2023-04-26T14:23:59+00:00
d3d11_fmt: allow build D3D11 modules with C++
as in 6b7a6d86ae30109bed34fec0b5ffc1f013ca4a81
- - - - -
490bcd81 by Steve Lhomme at 2023-04-26T14:23:59+00:00
d3d11_fmt: avoid forcing COBJMACROS on files including the header
(cherry picked from commit 65048467c5f394fcc5c577e69a732bdfd1f1dd70) (edited)
edited:
* FindD3D11Format doesn't use an undef in 4.0
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
188c5b96 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: get source D3D11_TEXTURE2D_DESC early
(cherry picked from commit e4ba931b3d2a6604471f196ddabdedcc9d181f8a) (edited)
edited:
* the direct3d11 code is in C++ in 4.0 (GetDesc called directly)
* the pic_quad is split in generic and D3D11 parts in 4.0
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
aa52c643 by Steve Lhomme at 2023-04-26T14:23:59+00:00
win32/common: only get the size of the Window
The top/left is always zero.
- - - - -
254d230f by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: move code to avoid forward declaration
No functional changes.
- - - - -
7ad94cd1 by Steve Lhomme at 2023-04-26T14:23:59+00:00
vout/win32: allow forcing the source size
(cherry picked from commit d4374090ee1ae8a28b46236a89418df3a722871c) (edited)
edited:
* the format is not passed to CommonInit() in 3.0
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
92e523bd by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: keep the format used to create the pool
- - - - -
fb2552f0 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: add an option to select the upscaling quality
D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT is smoother but a bit slower.
Users may prefer sharper/blockier outputs.
We only force point sampler to the blocky version as SPUs also use this
to make the text smoother.
(cherry picked from commit b86a57876f2cff622be637a66aaf6973ec2018b5)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
a6870065 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: keep the format used with the pic_quad
(cherry picked from commit 794d897d07ff45b0c60bcbddec1e0705aa157853)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
3b520d80 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: add video processor based scaler
The VideoProcessor may use some special scaling in hardware that might do a
better job than the linear sampler in the shader.
Co-authored-by: Chilledheart <hukeyue at hotmail.com>
(cherry picked from commit 1f7f849ce18cbdd47c1bdf0a4ffcb0dbdbb6aa6e) (edited)
edited:
* 3.0 doesn't have DXGI_MAX_SHADER_VIEW
* 3.0 doesn't have DXGI_RGB_FORMAT or DXGI_YUV_FORMAT
* 3.0 doesn't have DXGI_CHROMA_GPU
* use a memcmp of the vout_display_place_t instead of vout_display_PlaceEquals()
* pass a vout_display_cfg_t instead of vout_display_placement which does
not exist in 3.0
* set is_display_filled instead of VLC_VIDEO_FIT_SMALLER
* D3D11_AllocateResourceView is called D3D11_AllocateShaderView in 3.0
* 3.0 uses a picture_sys_t instead of picture_sys_d3d11_t
* 4.0 also has the meson changes
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
5f10bc7c by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: use NVIDIA super-resolution upscaler
Co-authored-by: Steve Lhomme <robux4 at ycbcr.xyz>
(cherry picked from commit beac9098dbe49c6e18e842c19dd773c1b395ddef) (edited)
edited:
* the direct3d11 is in C++ in4.0
* 3.0 doesn't have DXGI_RGB_FORMAT or DXGI_YUV_FORMAT
* 3.0 doesn't have DXGI_CHROMA_GPU
* the d3d_dev is a pointer in 4.0
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
467cd307 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: add Intel based super resolution
(cherry picked from commit 8892ebd6f1735fde6433473e7737767733a180ae)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
- - - - -
56222b92 by Steve Lhomme at 2023-04-26T14:23:59+00:00
direct3d11: remove unneeded forward declaration
- - - - -
8 changed files:
- modules/video_chroma/d3d11_fmt.c
- modules/video_chroma/d3d11_fmt.h
- modules/video_output/Makefile.am
- modules/video_output/win32/common.c
- modules/video_output/win32/common.h
- + modules/video_output/win32/d3d11_scaler.cpp
- + modules/video_output/win32/d3d11_scaler.h
- modules/video_output/win32/direct3d11.c
Changes:
=====================================
modules/video_chroma/d3d11_fmt.c
=====================================
@@ -503,6 +503,14 @@ done:
return result;
}
+bool DeviceSupportsFormat(ID3D11Device *d3ddevice, DXGI_FORMAT format, UINT supportFlags)
+{
+ UINT i_formatSupport;
+ return SUCCEEDED( ID3D11Device_CheckFormatSupport(d3ddevice, format,
+ &i_formatSupport) )
+ && ( i_formatSupport & supportFlags ) == supportFlags;
+}
+
#undef FindD3D11Format
const d3d_format_t *FindD3D11Format(vlc_object_t *o,
d3d11_device_t *d3d_dev,
=====================================
modules/video_chroma/d3d11_fmt.h
=====================================
@@ -28,6 +28,15 @@
#include "dxgi_fmt.h"
+#ifdef __cplusplus
+extern "C" {
+
+#ifndef IID_GRAPHICS_PPV_ARGS
+#define IID_GRAPHICS_PPV_ARGS(ppType) IID_PPV_ARGS(ppType)
+#endif
+
+#endif
+
DEFINE_GUID(GUID_CONTEXT_MUTEX, 0x472e8835, 0x3f8e, 0x4f93, 0xa0, 0xcb, 0x25, 0x79, 0x77, 0x6c, 0xed, 0x86);
/* see https://msdn.microsoft.com/windows/hardware/commercialize/design/compatibility/device-graphics */
@@ -121,14 +130,7 @@ int D3D11CheckDriverVersion(const d3d11_device_t *, UINT vendorId,
void D3D11_GetDriverVersion(vlc_object_t *, d3d11_device_t *);
#define D3D11_GetDriverVersion(a,b) D3D11_GetDriverVersion(VLC_OBJECT(a),b)
-static inline bool DeviceSupportsFormat(ID3D11Device *d3ddevice,
- DXGI_FORMAT format, UINT supportFlags)
-{
- UINT i_formatSupport;
- return SUCCEEDED( ID3D11Device_CheckFormatSupport(d3ddevice, format,
- &i_formatSupport) )
- && ( i_formatSupport & supportFlags ) == supportFlags;
-}
+bool DeviceSupportsFormat(ID3D11Device *d3ddevice, DXGI_FORMAT format, UINT supportFlags);
const d3d_format_t *FindD3D11Format(vlc_object_t *,
d3d11_device_t*,
@@ -163,4 +165,8 @@ static inline void d3d11_device_unlock(d3d11_device_t *d3d_dev)
ReleaseMutex( d3d_dev->context_mutex );
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /* include-guard */
=====================================
modules/video_output/Makefile.am
=====================================
@@ -278,7 +278,8 @@ endif
libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \
video_output/win32/d3d11_quad.c video_output/win32/d3d11_quad.h \
video_output/win32/d3d11_shaders.c video_output/win32/d3d11_shaders.h \
- video_output/win32/common.c video_output/win32/common.h
+ video_output/win32/common.c video_output/win32/common.h \
+ video_output/win32/d3d11_scaler.cpp video_output/win32/d3d11_scaler.h
libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_direct3d11
libdirect3d11_plugin_la_LIBADD = libchroma_copy.la libd3d11_common.la $(LIBCOM) -luuid
=====================================
modules/video_output/win32/common.c
=====================================
@@ -55,9 +55,14 @@ static void CommonChangeThumbnailClip(vout_display_t *, bool show);
#if !VLC_WINSTORE_APP
static int CommonControlSetFullscreen(vout_display_t *, bool is_fullscreen);
-static bool GetRect(const vout_display_sys_t *sys, RECT *out)
+static bool GetWindowSize(const vout_display_sys_t *sys, UINT *w, UINT *h)
{
- return GetClientRect(sys->hwnd, out);
+ RECT out;
+ if (!GetClientRect(sys->hwnd, &out))
+ return false;
+ *w = out.right; // out.left is zero
+ *h = out.bottom; // out.top is zero
+ return true;
}
#endif
@@ -87,7 +92,7 @@ int CommonInit(vout_display_t *vd)
sys->pf_GetPictureWidth = GetPictureWidth;
sys->pf_GetPictureHeight = GetPictureHeight;
#if !VLC_WINSTORE_APP
- sys->pf_GetRect = GetRect;
+ sys->pf_GetWindowSize = GetWindowSize;
SetRectEmpty(&sys->rect_display);
SetRectEmpty(&sys->rect_parent);
@@ -114,6 +119,8 @@ int CommonInit(vout_display_t *vd)
cfg.width = vd->cfg->display.width;
cfg.height = vd->cfg->display.height;
+ sys->src_fmt = &vd->source;
+
event_hwnd_t hwnd;
if (EventThreadStart(sys->event, &hwnd, &cfg))
return VLC_EGENERIC;
@@ -156,13 +163,12 @@ void UpdateRects(vout_display_t *vd,
bool is_forced)
{
vout_display_sys_t *sys = vd->sys;
- const video_format_t *source = &vd->source;
+ const video_format_t *source = sys->src_fmt;
#define rect_src sys->rect_src
#define rect_src_clipped sys->rect_src_clipped
#define rect_dest sys->rect_dest
#define rect_dest_clipped sys->rect_dest_clipped
- RECT rect;
POINT point;
/* */
@@ -170,7 +176,8 @@ void UpdateRects(vout_display_t *vd,
cfg = vd->cfg;
/* Retrieve the window size */
- if (!sys->pf_GetRect(sys, &rect))
+ UINT window_width, window_height;
+ if (!sys->pf_GetWindowSize(sys, &window_width, &window_height))
return;
/* Retrieve the window position */
@@ -186,27 +193,31 @@ void UpdateRects(vout_display_t *vd,
if (unlikely(!sys->event)) // external rendering
{
has_moved = false;
- is_resized = rect.right != (sys->rect_display.right - sys->rect_display.left) ||
- rect.bottom != (sys->rect_display.bottom - sys->rect_display.top);
- sys->rect_display = rect;
+ is_resized =
+ window_width != (UINT)(sys->rect_display.right - sys->rect_display.left) ||
+ window_height != (UINT)(sys->rect_display.bottom - sys->rect_display.top);
+ sys->rect_display.left = 0;
+ sys->rect_display.top = 0;
+ sys->rect_display.right = window_width;
+ sys->rect_display.bottom = window_height;
}
#if !VLC_WINSTORE_APP
else
{
EventThreadUpdateWindowPosition(sys->event, &has_moved, &is_resized,
point.x, point.y,
- rect.right, rect.bottom);
+ window_width, window_height);
}
#endif
if (is_resized)
- vout_display_SendEventDisplaySize(vd, rect.right, rect.bottom);
+ vout_display_SendEventDisplaySize(vd, window_width, window_height);
if (!is_forced && !has_moved && !is_resized)
return;
/* Update the window position and size */
vout_display_cfg_t place_cfg = *cfg;
- place_cfg.display.width = rect.right;
- place_cfg.display.height = rect.bottom;
+ place_cfg.display.width = window_width;
+ place_cfg.display.height = window_height;
#if (defined(MODULE_NAME_IS_glwin32))
/* Reverse vertical alignment as the GL tex are Y inverted */
=====================================
modules/video_output/win32/common.h
=====================================
@@ -67,6 +67,7 @@ typedef struct vout_display_sys_win32_t
RECT rect_src_clipped;
RECT rect_dest;
RECT rect_dest_clipped;
+ const video_format_t *src_fmt;
picture_pool_t *pool;
@@ -79,7 +80,7 @@ typedef struct vout_display_sys_win32_t
int i_align_dest_boundary;
int i_align_dest_size;
- bool (*pf_GetRect)(const struct vout_display_sys_win32_t *p_sys, RECT *out);
+ bool (*pf_GetWindowSize)(const struct vout_display_sys_win32_t *p_sys, UINT *w, UINT *h);
unsigned int (*pf_GetPictureWidth) (const vout_display_t *);
unsigned int (*pf_GetPictureHeight)(const vout_display_t *);
} vout_display_sys_win32_t;
=====================================
modules/video_output/win32/d3d11_scaler.cpp
=====================================
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*****************************************************************************
+ * d3d11_scaler: Direct3D11 VideoProcessor based output scaling
+ *****************************************************************************
+ * Copyright © 2023 Videolabs, VLC authors and VideoLAN
+ *
+ * Authors: Chilledheart <hukeyue at hotmail.com>
+ * Steve Lhomme <robux4 at videolabs.io>
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "d3d11_scaler.h"
+
+#include <new>
+#include <wrl/client.h>
+using Microsoft::WRL::ComPtr;
+
+struct d3d11_scaler
+{
+ bool usable = false;
+ const d3d_format_t *d3d_fmt = nullptr;
+ vout_display_place_t place = {};
+ bool super_res = false;
+ bool upscaling = false;
+ UINT Width = 0;
+ UINT Height = 0;
+ ComPtr<ID3D11VideoDevice> d3dviddev;
+ ComPtr<ID3D11VideoContext> d3dvidctx;
+ ComPtr<ID3D11VideoProcessorEnumerator> enumerator;
+ ComPtr<ID3D11VideoProcessor> processor;
+ ComPtr<ID3D11VideoProcessorOutputView> outputView;
+ ID3D11ShaderResourceView *SRVs[D3D11_MAX_SHADER_VIEW] = {};
+};
+
+static const d3d_format_t *GetDirectRenderingFormat(vlc_object_t *vd, d3d11_device_t *d3d_dev, vlc_fourcc_t i_src_chroma)
+{
+ UINT supportFlags = D3D11_FORMAT_SUPPORT_SHADER_LOAD | D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT;
+ return (FindD3D11Format)( vd, d3d_dev, i_src_chroma, false, 0, 0, 0, is_d3d11_opaque(i_src_chroma), supportFlags );
+}
+
+d3d11_scaler *D3D11_UpscalerCreate(vlc_object_t *vd, d3d11_device_t *d3d_dev, vlc_fourcc_t i_chroma,
+ bool super_res)
+{
+ bool canProcess = !super_res;
+ // NVIDIA 530+ driver
+ if (d3d_dev->adapterDesc.VendorId == GPU_MANUFACTURER_NVIDIA &&
+ (d3d_dev->WDDM.revision * 10000 + d3d_dev->WDDM.build) > 153000)
+ {
+ // TODO refine which GPU can do it
+ canProcess = true;
+ }
+ else if (d3d_dev->adapterDesc.VendorId == GPU_MANUFACTURER_INTEL)
+ {
+ // TODO refine which GPU and drivers can do it
+ canProcess = true;
+ }
+
+ if (!canProcess)
+ {
+ msg_Err(vd, "Super Resolution filter not supported");
+ return nullptr;
+ }
+
+ const d3d_format_t *fmt = GetDirectRenderingFormat(vd, d3d_dev, i_chroma);
+ if (fmt == nullptr || fmt->formatTexture == DXGI_FORMAT_UNKNOWN)
+ {
+ msg_Warn(vd, "chroma upscale of %4.4s not supported", (char*)&i_chroma);
+ return nullptr;
+ }
+
+ d3d11_scaler *scaleProc = new (std::nothrow) d3d11_scaler;
+ if (unlikely(scaleProc == nullptr))
+ return nullptr;
+
+ HRESULT hr;
+ hr = d3d_dev->d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(&scaleProc->d3dviddev));
+ if (unlikely(FAILED(hr)))
+ {
+ msg_Err(vd, "Could not Query ID3D11VideoDevice Interface. (hr=0x%lX)", hr);
+ goto error;
+ }
+
+ hr = d3d_dev->d3dcontext->QueryInterface(IID_GRAPHICS_PPV_ARGS(&scaleProc->d3dvidctx));
+ if (unlikely(FAILED(hr)))
+ {
+ msg_Err(vd, "Could not Query ID3D11VideoContext Interface. (hr=0x%lX)", hr);
+ goto error;
+ }
+
+ scaleProc->d3d_fmt = fmt;
+ scaleProc->super_res = super_res;
+ return scaleProc;
+error:
+ delete scaleProc;
+ return nullptr;
+}
+
+static void ReleaseSRVs(d3d11_scaler *scaleProc)
+{
+ for (size_t i=0; i<ARRAY_SIZE(scaleProc->SRVs); i++)
+ {
+ if (scaleProc->SRVs[i])
+ {
+ scaleProc->SRVs[i]->Release();
+ scaleProc->SRVs[i] = nullptr;
+ }
+ }
+}
+
+int D3D11_UpscalerUpdate(vlc_object_t *vd, d3d11_scaler *scaleProc, d3d11_device_t*d3d_dev,
+ const video_format_t *fmt, video_format_t *quad_fmt,
+ const vout_display_cfg_t *cfg)
+{
+ HRESULT hr;
+ ID3D11Texture2D *_upscaled[D3D11_MAX_SHADER_VIEW];
+ ComPtr<ID3D11Texture2D> upscaled;
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outDesc{ };
+ D3D11_VIDEO_COLOR black{};
+ black.RGBA.A = 1.f;
+ bool upscale = false;
+
+ vout_display_place_t place{};
+ auto display = *cfg;
+ display.is_display_filled = true;
+ vout_display_PlacePicture(&place, fmt, &display, true);
+
+ unsigned out_width, out_height;
+ out_width = (display.display.width + (scaleProc->d3d_fmt->widthDenominator-1)) & ~(scaleProc->d3d_fmt->widthDenominator-1);
+ out_height = (display.display.height + (scaleProc->d3d_fmt->heightDenominator-1)) & ~(scaleProc->d3d_fmt->heightDenominator-1);
+
+ quad_fmt->i_x_offset = 0;
+ quad_fmt->i_width = quad_fmt->i_visible_width = out_width;
+ quad_fmt->i_y_offset = 0;
+ quad_fmt->i_height = quad_fmt->i_visible_height = out_height;
+
+ if (scaleProc->Width == out_width && scaleProc->Height == out_height &&
+ memcmp(&scaleProc->place, &place, sizeof(place)) == 0)
+ // do nothing
+ return VLC_SUCCESS;
+ scaleProc->place = place;
+
+ scaleProc->usable = false;
+
+ if (scaleProc->enumerator.Get() == nullptr)
+ {
+ d3d11_device_lock(d3d_dev);
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC processorDesc{};
+ processorDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+ processorDesc.InputFrameRate = {
+ .Numerator = fmt->i_frame_rate,
+ .Denominator = fmt->i_frame_rate_base,
+ };
+ processorDesc.InputWidth = fmt->i_width;
+ processorDesc.InputHeight = fmt->i_height;
+ processorDesc.OutputWidth = out_width;
+ processorDesc.OutputHeight = out_height;
+ processorDesc.OutputFrameRate = {
+ .Numerator = fmt->i_frame_rate,
+ .Denominator = fmt->i_frame_rate_base,
+ };
+ processorDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
+ hr = scaleProc->d3dviddev->CreateVideoProcessorEnumerator(&processorDesc, &scaleProc->enumerator);
+ if (FAILED(hr))
+ {
+ msg_Dbg(vd, "Can't get a video processor for the video (error 0x%lx).", hr);
+ d3d11_device_unlock(d3d_dev);
+ goto done_super;
+ }
+
+ hr = scaleProc->d3dviddev->CreateVideoProcessor(scaleProc->enumerator.Get(), 0,
+ &scaleProc->processor);
+ d3d11_device_unlock(d3d_dev);
+ if (FAILED(hr))
+ {
+ msg_Dbg(vd, "failed to create the processor (error 0x%lx).", hr);
+ goto done_super;
+ }
+ }
+
+ if (scaleProc->Width != out_width || scaleProc->Height != out_height )
+ {
+ scaleProc->Width = out_width;
+ scaleProc->Height = out_height;
+
+ // we need a texture that will receive the upscale version
+ D3D11_TEXTURE2D_DESC texDesc;
+ ZeroMemory(&texDesc, sizeof(texDesc));
+ texDesc.MipLevels = 1;
+ texDesc.SampleDesc.Count = 1;
+ texDesc.MiscFlags = 0;
+ texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ texDesc.Usage = D3D11_USAGE_DEFAULT;
+ texDesc.CPUAccessFlags = 0;
+ texDesc.ArraySize = 1;
+ texDesc.Format = scaleProc->d3d_fmt->formatTexture;
+ texDesc.Width = scaleProc->Width;
+ texDesc.Height = scaleProc->Height;
+ hr = d3d_dev->d3ddevice->CreateTexture2D(&texDesc, nullptr, upscaled.GetAddressOf());
+ if (FAILED(hr))
+ {
+ msg_Err(vd, "Failed to create the upscale texture. (hr=0x%lX)", hr);
+ goto done_super;
+ }
+ msg_Dbg(vd, "upscale resolution %ux%u", texDesc.Width, texDesc.Height);
+
+ outDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
+ outDesc.Texture2D.MipSlice = 0;
+
+ hr = scaleProc->d3dviddev->CreateVideoProcessorOutputView(
+ upscaled.Get(),
+ scaleProc->enumerator.Get(),
+ &outDesc,
+ scaleProc->outputView.ReleaseAndGetAddressOf());
+ if (FAILED(hr))
+ {
+ msg_Dbg(vd,"Failed to create processor output. (hr=0x%lX)", hr);
+ goto done_super;
+ }
+
+ ReleaseSRVs(scaleProc);
+ _upscaled[0] = upscaled.Get();
+ _upscaled[1] = upscaled.Get();
+ _upscaled[2] = upscaled.Get();
+ _upscaled[3] = upscaled.Get();
+ if ((D3D11_AllocateShaderView)(vd, d3d_dev->d3ddevice, scaleProc->d3d_fmt,
+ _upscaled, 0, scaleProc->SRVs) != VLC_SUCCESS)
+ goto done_super;
+ }
+
+ RECT srcRect;
+ srcRect.left = fmt->i_x_offset;
+ srcRect.top = fmt->i_y_offset;
+ srcRect.right = srcRect.left + fmt->i_visible_width;
+ srcRect.bottom = srcRect.top + fmt->i_visible_height;
+
+ RECT dstRect;
+ dstRect.left = place.x;
+ dstRect.top = place.y;
+ dstRect.right = dstRect.left + place.width;
+ dstRect.bottom = dstRect.top + place.height;
+
+ d3d11_device_lock(d3d_dev);
+ scaleProc->d3dvidctx->VideoProcessorSetStreamSourceRect(scaleProc->processor.Get(),
+ 0, TRUE, &srcRect);
+
+ scaleProc->d3dvidctx->VideoProcessorSetStreamDestRect(scaleProc->processor.Get(),
+ 0, TRUE, &dstRect);
+
+ scaleProc->d3dvidctx->VideoProcessorSetOutputBackgroundColor(scaleProc->processor.Get(),
+ 0, &black);
+
+ if (scaleProc->super_res)
+ {
+ // only use super resolution when source is smaller than display
+ upscale = fmt->i_visible_width < place.width
+ || fmt->i_visible_height < place.height;
+
+ if (d3d_dev->adapterDesc.VendorId == GPU_MANUFACTURER_NVIDIA)
+ {
+ constexpr GUID kNvidiaPPEInterfaceGUID{ 0xd43ce1b3, 0x1f4b, 0x48ac, {0xba, 0xee, 0xc3, 0xc2, 0x53, 0x75, 0xe6, 0xf7} };
+ constexpr UINT kStreamExtensionVersionV1 = 0x1;
+ constexpr UINT kStreamExtensionMethodRTXVSR = 0x2;
+ struct {
+ UINT version;
+ UINT method;
+ UINT enable;
+ } stream_extension_info = {
+ kStreamExtensionVersionV1,
+ kStreamExtensionMethodRTXVSR,
+ upscale ? 1u : 0u,
+ };
+
+ hr = scaleProc->d3dvidctx->VideoProcessorSetStreamExtension(
+ scaleProc->processor.Get(),
+ 0, &kNvidiaPPEInterfaceGUID, sizeof(stream_extension_info),
+ &stream_extension_info);
+
+ if (FAILED(hr)) {
+ msg_Err(vd, "Failed to set the NVIDIA video process stream extension. (hr=0x%lX)", hr);
+ d3d11_device_unlock(d3d_dev);
+ goto done_super;
+ }
+ }
+ else if (d3d_dev->adapterDesc.VendorId == GPU_MANUFACTURER_INTEL)
+ {
+ constexpr GUID GUID_INTEL_VPE_INTERFACE{ 0xedd1d4b9, 0x8659, 0x4cbc, {0xa4, 0xd6, 0x98, 0x31, 0xa2, 0x16, 0x3a, 0xc3}};
+
+ constexpr UINT kIntelVpeFnVersion = 0x01;
+ constexpr UINT kIntelVpeFnMode = 0x20;
+ constexpr UINT kIntelVpeFnScaling = 0x37;
+
+ // values for kIntelVpeFnVersion
+ constexpr UINT kIntelVpeVersion3 = 0x0003;
+
+ // values for kIntelVpeFnMode
+ constexpr UINT kIntelVpeModeNone = 0x0;
+ constexpr UINT kIntelVpeModePreproc = 0x1;
+
+ // values for kIntelVpeFnScaling
+ constexpr UINT kIntelVpeScalingDefault = 0x0;
+ constexpr UINT kIntelVpeScalingSuperResolution = 0x2;
+
+ UINT param;
+ struct {
+ UINT function;
+ void *param;
+ } ext = {
+ 0,
+ ¶m,
+ };
+
+ ext.function = kIntelVpeFnVersion;
+ param = kIntelVpeVersion3;
+ hr = scaleProc->d3dvidctx->VideoProcessorSetOutputExtension(
+ scaleProc->processor.Get(),
+ &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
+
+ if (FAILED(hr)) {
+ msg_Err(vd, "Failed to set the Intel VPE version. (hr=0x%lX)", hr);
+ d3d11_device_unlock(d3d_dev);
+ goto done_super;
+ }
+
+ ext.function = kIntelVpeFnMode;
+ param = upscale ? kIntelVpeModePreproc : kIntelVpeModeNone;
+ hr = scaleProc->d3dvidctx->VideoProcessorSetOutputExtension(
+ scaleProc->processor.Get(),
+ &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
+ if (FAILED(hr)) {
+ msg_Err(vd, "Failed to set the Intel VPE mode. (hr=0x%lX)", hr);
+ d3d11_device_unlock(d3d_dev);
+ goto done_super;
+ }
+
+ ext.function = kIntelVpeFnScaling;
+ param = upscale ? kIntelVpeScalingSuperResolution : kIntelVpeScalingDefault;
+ hr = scaleProc->d3dvidctx->VideoProcessorSetOutputExtension(
+ scaleProc->processor.Get(),
+ &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
+ if (FAILED(hr)) {
+ msg_Err(vd, "Failed to set the Intel VPE scaling type. (hr=0x%lX)", hr);
+ d3d11_device_unlock(d3d_dev);
+ goto done_super;
+ }
+ }
+ }
+ d3d11_device_unlock(d3d_dev);
+
+ if (scaleProc->upscaling != upscale)
+ {
+ msg_Dbg(vd, "turning VSR %s", upscale ? "ON" : "OFF");
+ scaleProc->upscaling = upscale;
+ }
+
+ scaleProc->usable = true;
+ return VLC_SUCCESS;
+done_super:
+ ReleaseSRVs(scaleProc);
+ scaleProc->processor.Reset();
+ scaleProc->enumerator.Reset();
+ return VLC_EGENERIC;
+}
+
+void D3D11_UpscalerDestroy(d3d11_scaler *scaleProc)
+{
+ ReleaseSRVs(scaleProc);
+ delete scaleProc;
+}
+
+
+static int assert_ProcessorInput(vlc_object_t *vd, d3d11_scaler *scaleProc, picture_sys_t *p_sys_src)
+{
+ if (!p_sys_src->processorInput)
+ {
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inDesc{};
+ inDesc.FourCC = 0;
+ inDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
+ inDesc.Texture2D.MipSlice = 0;
+ inDesc.Texture2D.ArraySlice = p_sys_src->slice_index;
+
+ HRESULT hr;
+
+ hr = scaleProc->d3dviddev->CreateVideoProcessorInputView(
+ p_sys_src->resource[KNOWN_DXGI_INDEX],
+ scaleProc->enumerator.Get(),
+ &inDesc,
+ &p_sys_src->processorInput);
+ if (FAILED(hr))
+ {
+#ifndef NDEBUG
+ msg_Dbg(vd,"Failed to create processor input for slice %d. (hr=0x%lX)", p_sys_src->slice_index, hr);
+#endif
+ return VLC_EGENERIC;
+ }
+ }
+ return VLC_SUCCESS;
+}
+
+int D3D11_UpscalerScale(vlc_object_t *vd, d3d11_scaler *scaleProc, picture_sys_t *p_sys)
+{
+ HRESULT hr;
+
+ if (assert_ProcessorInput(vd, scaleProc, p_sys) != VLC_SUCCESS)
+ {
+ msg_Err(vd, "fail to create upscaler input");
+ return VLC_EGENERIC;
+ }
+
+ D3D11_VIDEO_PROCESSOR_STREAM stream{};
+ stream.Enable = TRUE;
+ stream.pInputSurface = p_sys->processorInput;
+
+ hr = scaleProc->d3dvidctx->VideoProcessorBlt(scaleProc->processor.Get(),
+ scaleProc->outputView.Get(),
+ 0, 1, &stream);
+ if (FAILED(hr))
+ {
+ msg_Err(vd, "Failed to render the upscaled texture. (hr=0x%lX)", hr);
+ return VLC_EGENERIC;
+ }
+ return VLC_SUCCESS;
+}
+
+void D3D11_UpscalerGetSize(const d3d11_scaler *scaleProc, unsigned *i_width, unsigned *i_height)
+{
+ *i_width = scaleProc->Width;
+ *i_height = scaleProc->Height;
+}
+
+bool D3D11_UpscalerUsed(const d3d11_scaler *scaleProc)
+{
+ return scaleProc->usable;
+}
+
+void D3D11_UpscalerGetSRV(const d3d11_scaler *scaleProc, ID3D11ShaderResourceView *SRV[D3D11_MAX_SHADER_VIEW])
+{
+ for (size_t i=0; i<D3D11_MAX_SHADER_VIEW; i++)
+ SRV[i] = scaleProc->SRVs[i];
+}
=====================================
modules/video_output/win32/d3d11_scaler.h
=====================================
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*****************************************************************************
+ * d3d11_scaler: Direct3D11 VideoProcessor based output scaling
+ *****************************************************************************
+ * Copyright © 2023 Videolabs, VLC authors and VideoLAN
+ *
+ * Authors: Chilledheart <hukeyue at hotmail.com>
+ * Steve Lhomme <robux4 at videolabs.io>
+ *****************************************************************************/
+
+#ifndef VLC_D3D11_SCALER_H
+#define VLC_D3D11_SCALER_H
+
+#include "../../video_chroma/d3d11_fmt.h"
+#include <vlc_vout_display.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct d3d11_scaler;
+
+struct d3d11_scaler *D3D11_UpscalerCreate(vlc_object_t *, d3d11_device_t*, vlc_fourcc_t i_chroma, bool super_res);
+void D3D11_UpscalerDestroy(struct d3d11_scaler *);
+int D3D11_UpscalerUpdate(vlc_object_t *, struct d3d11_scaler *, d3d11_device_t*,
+ const video_format_t *, video_format_t *,
+ const vout_display_cfg_t *);
+int D3D11_UpscalerScale(vlc_object_t *, struct d3d11_scaler *, picture_sys_t *);
+bool D3D11_UpscalerUsed(const struct d3d11_scaler *);
+void D3D11_UpscalerGetSRV(const struct d3d11_scaler *, ID3D11ShaderResourceView *SRV[D3D11_MAX_SHADER_VIEW]);
+void D3D11_UpscalerGetSize(const struct d3d11_scaler *, unsigned *i_width, unsigned *i_height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // VLC_D3D11_SCALER_H
=====================================
modules/video_output/win32/direct3d11.c
=====================================
@@ -55,6 +55,7 @@
#include "../../video_chroma/d3d11_fmt.h"
#include "d3d11_quad.h"
#include "d3d11_shaders.h"
+#include "d3d11_scaler.h"
#include "common.h"
@@ -69,6 +70,14 @@ static void Close(vlc_object_t *);
#define HW_BLENDING_LONGTEXT N_(\
"Try to use hardware acceleration for subtitle/OSD blending.")
+#define UPSCALE_MODE_TEXT N_("Video Upscaling Mode")
+#define UPSCALE_MODE_LONGTEXT N_("Select the upscaling mode for video.")
+
+static const char *const ppsz_upscale_mode[] = {
+ "linear", "point", "processor", "super" };
+static const char *const ppsz_upscale_mode_text[] = {
+ N_("Linear Sampler"), N_("Point Sampler"), N_("Video Processor"), N_("Super Resolution") };
+
vlc_module_begin ()
set_shortname("Direct3D11")
set_description(N_("Direct3D11 video output"))
@@ -83,14 +92,26 @@ vlc_module_begin ()
add_integer("winrt-swapchain", 0x0, NULL, NULL, true) /* IDXGISwapChain1* */
change_volatile()
+ add_string("d3d11-upscale-mode", "linear", UPSCALE_MODE_TEXT, UPSCALE_MODE_LONGTEXT, false)
+ change_string_list(ppsz_upscale_mode, ppsz_upscale_mode_text)
+
set_capability("vout display", 300)
add_shortcut("direct3d11")
set_callbacks(Open, Close)
vlc_module_end ()
+enum d3d11_upscale
+{
+ upscale_LinearSampler,
+ upscale_PointSampler,
+ upscale_VideoProcessor,
+ upscale_SuperResolution,
+};
+
struct vout_display_sys_t
{
vout_display_sys_win32_t sys;
+ video_format_t pool_fmt;
int log_level;
@@ -102,6 +123,7 @@ struct vout_display_sys_t
IDXGISwapChain4 *dxgiswapChain4; /* DXGI 1.5 for HDR */
d3d11_device_t d3d_dev;
d3d_quad_t picQuad;
+ video_format_t quad_fmt;
#ifdef HAVE_D3D11_4_H
ID3D11Fence *d3dRenderFence;
@@ -129,6 +151,10 @@ struct vout_display_sys_t
const d3d_format_t *d3dregion_format;
int d3dregion_count;
picture_t **d3dregions;
+
+ // upscaling
+ enum d3d11_upscale upscaleMode;
+ struct d3d11_scaler *scaleProc;
};
#define RECTWidth(r) (int)((r).right - (r).left)
@@ -149,8 +175,6 @@ static int Direct3D11CreateFormatResources (vout_display_t *, const video_forma
static int Direct3D11CreateGenericResources(vout_display_t *);
static void Direct3D11DestroyResources(vout_display_t *);
-static void Direct3D11DestroyPool(vout_display_t *);
-
static void DestroyDisplayPoolPicture(picture_t *);
static void Direct3D11DeleteRegions(int, picture_t **);
static int Direct3D11MapSubpicture(vout_display_t *, int *, picture_t ***, subpicture_t *);
@@ -192,11 +216,9 @@ static void Direct3D11UnmapPoolTexture(picture_t *picture)
ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX], 0);
}
-static bool GetRect(const vout_display_sys_win32_t *p_sys, RECT *out)
+static bool GetWinRTSize(const vout_display_sys_win32_t *p_sys, UINT *w, UINT *h)
{
const vout_display_sys_t *sys = (const vout_display_sys_t *)p_sys;
- out->left = 0;
- out->top = 0;
uint32_t i_width;
uint32_t i_height;
UINT dataSize = sizeof(i_width);
@@ -209,8 +231,8 @@ static bool GetRect(const vout_display_sys_win32_t *p_sys, RECT *out)
if (FAILED(hr)) {
return false;
}
- out->right = i_width;
- out->bottom = i_height;
+ *w = i_width;
+ *h = i_height;
return true;
}
@@ -235,7 +257,7 @@ static int OpenCoreW(vout_display_t *vd)
IDXGISwapChain_AddRef (sys->dxgiswapChain);
ID3D11DeviceContext_AddRef(sys->d3d_dev.d3dcontext);
- sys->sys.pf_GetRect = GetRect;
+ sys->sys.pf_GetWindowSize = GetWinRTSize;
return VLC_SUCCESS;
}
@@ -352,14 +374,10 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
if (vd->info.is_slow)
pool_size = 1;
- video_format_t surface_fmt = vd->fmt;
- surface_fmt.i_width = sys->picQuad.i_width;
- surface_fmt.i_height = sys->picQuad.i_height;
-
- if (D3D11_SetupQuad( vd, &sys->d3d_dev, &surface_fmt, &sys->picQuad, &sys->display, &sys->sys.rect_src_clipped,
+ if (D3D11_SetupQuad( vd, &sys->d3d_dev, &sys->quad_fmt, &sys->picQuad, &sys->display, &sys->sys.rect_src_clipped,
vd->fmt.projection_mode == PROJECTION_MODE_RECTANGULAR ? sys->flatVSShader : sys->projectionVSShader,
sys->pVertexLayout,
- surface_fmt.projection_mode, vd->fmt.orientation ) != VLC_SUCCESS) {
+ sys->quad_fmt.projection_mode, vd->fmt.orientation ) != VLC_SUCCESS) {
msg_Err(vd, "Could not Create the main quad picture.");
return NULL;
}
@@ -379,7 +397,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
}
if (sys->picQuad.formatInfo->formatTexture == DXGI_FORMAT_UNKNOWN)
- sys->sys.pool = picture_pool_NewFromFormat( &surface_fmt, pool_size );
+ sys->sys.pool = picture_pool_NewFromFormat( &sys->pool_fmt, pool_size );
else
{
ID3D11Texture2D *textures[pool_size * D3D11_MAX_SHADER_VIEW];
@@ -389,7 +407,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
/* only provide enough for the filters, we can still do direct rendering */
slices = __MIN(slices, 6);
- if (AllocateTextures(vd, &sys->d3d_dev, sys->picQuad.formatInfo, &surface_fmt, slices, textures))
+ if (AllocateTextures(vd, &sys->d3d_dev, sys->picQuad.formatInfo, &sys->pool_fmt, slices, textures))
goto error;
pictures = calloc(pool_size, sizeof(*pictures));
@@ -421,7 +439,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
.pf_destroy = DestroyDisplayPoolPicture,
};
- picture = picture_NewFromResource(&surface_fmt, &resource);
+ picture = picture_NewFromResource(&sys->pool_fmt, &resource);
if (unlikely(picture == NULL)) {
free(picsys);
msg_Err( vd, "Failed to create picture %d in the pool.", picture_count );
@@ -434,7 +452,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
}
#ifdef HAVE_ID3D11VIDEODECODER
- if (is_d3d11_opaque(surface_fmt.i_chroma) && !sys->legacy_shader)
+ if (is_d3d11_opaque(sys->pool_fmt.i_chroma) && !sys->legacy_shader)
#endif
{
sys->picQuad.resourceCount = DxgiResourceCount(sys->picQuad.formatInfo);
@@ -452,7 +470,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
.picture = pictures,
.picture_count = pool_size,
};
- if (vd->info.is_slow && !is_d3d11_opaque(surface_fmt.i_chroma)) {
+ if (vd->info.is_slow && !is_d3d11_opaque(sys->pool_fmt.i_chroma)) {
pool_cfg.lock = Direct3D11MapPoolTexture;
//pool_cfg.unlock = Direct3D11UnmapPoolTexture;
}
@@ -475,7 +493,7 @@ error:
sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
} else {
msg_Dbg(vd, "D3D11 pool succeed with %d surfaces (%dx%d) context 0x%p",
- pool_size, surface_fmt.i_width, surface_fmt.i_height, sys->d3d_dev.d3dcontext);
+ pool_size, sys->pool_fmt.i_width, sys->pool_fmt.i_height, sys->d3d_dev.d3dcontext);
}
return sys->sys.pool;
}
@@ -552,7 +570,10 @@ static int UpdateSamplers(vout_display_t *vd)
d3d11_device_lock(&sys->d3d_dev);
ID3D11SamplerState *d3dsampState[2];
- sampDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+ if (sys->upscaleMode == upscale_PointSampler)
+ sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
+ else
+ sampDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
hr = ID3D11Device_CreateSamplerState(sys->d3d_dev.d3ddevice, &sampDesc, &d3dsampState[0]);
if (FAILED(hr)) {
msg_Err(vd, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr);
@@ -583,11 +604,24 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
HRESULT hr;
ID3D11Texture2D* pDepthStencil;
ID3D11Texture2D* pBackBuffer;
- RECT rect;
- if (sys->sys.pf_GetRect != GetRect || !sys->sys.pf_GetRect(&sys->sys, &rect))
- rect = sys->sys.rect_dest_clipped;
- uint32_t i_width = RECTWidth(rect);
- uint32_t i_height = RECTHeight(rect);
+ UINT window_width, window_height;
+ bool proc_upscale = sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution;
+ if ((sys->sys.pf_GetWindowSize != GetWinRTSize && !proc_upscale)
+ || !sys->sys.pf_GetWindowSize(&sys->sys, &window_width, &window_height))
+ {
+ window_width = RECTWidth(sys->sys.rect_dest_clipped);
+ window_height = RECTHeight(sys->sys.rect_dest_clipped);
+ }
+
+ if (proc_upscale)
+ {
+ vout_display_cfg_t cfg = *vd->cfg;
+ cfg.display.width = window_width;
+ cfg.display.height = window_height;
+ D3D11_UpscalerUpdate(VLC_OBJECT(vd), sys->scaleProc, &sys->d3d_dev,
+ &sys->pool_fmt, &sys->quad_fmt, &cfg);
+ }
+
D3D11_TEXTURE2D_DESC dsc = { 0 };
if (sys->d3drenderTargetView) {
@@ -600,7 +634,7 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
}
}
- if (dsc.Width == i_width && dsc.Height == i_height)
+ if (dsc.Width == window_width && dsc.Height == window_height)
return S_OK; /* nothing changed */
if (sys->d3drenderTargetView) {
@@ -613,7 +647,7 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
}
/* TODO detect is the size is the same as the output and switch to fullscreen mode */
- hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 0, i_width, i_height,
+ hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 0, window_width, window_height,
DXGI_FORMAT_UNKNOWN, 0);
if (FAILED(hr)) {
msg_Err(vd, "Failed to resize the backbuffer. (hr=0x%lX)", hr);
@@ -639,8 +673,8 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
deptTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
deptTexDesc.CPUAccessFlags = 0;
deptTexDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
- deptTexDesc.Width = i_width;
- deptTexDesc.Height = i_height;
+ deptTexDesc.Width = window_width;
+ deptTexDesc.Height = window_height;
deptTexDesc.MipLevels = 1;
deptTexDesc.MiscFlags = 0;
deptTexDesc.SampleDesc.Count = 1;
@@ -851,6 +885,29 @@ static int Control(vout_display_t *vd, int query, va_list args)
RECT before_dest_clipped = sys->sys.rect_dest_clipped;
RECT before_dest = sys->sys.rect_dest;
+ if (sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution)
+ switch (query) {
+ case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+ case VOUT_DISPLAY_CHANGE_ZOOM:
+ case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
+ case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+ {
+ // update the source cropping
+ UINT window_width, window_height;
+ if (!sys->sys.pf_GetWindowSize(&sys->sys, &window_width, &window_height))
+ {
+ window_width = RECTWidth(sys->sys.rect_dest_clipped);
+ window_height = RECTHeight(sys->sys.rect_dest_clipped);
+ }
+ vout_display_cfg_t cfg = *vd->cfg;
+ cfg.display.width = window_width;
+ cfg.display.height = window_height;
+ D3D11_UpscalerUpdate(VLC_OBJECT(vd), sys->scaleProc, &sys->d3d_dev, &vd->source,
+ &sys->quad_fmt, &cfg);
+ }
+ break;
+ }
+
int res = CommonControl( vd, query, args );
if (query == VOUT_DISPLAY_CHANGE_VIEWPOINT)
@@ -890,6 +947,30 @@ static void Manage(vout_display_t *vd)
}
}
+static void CallUpdateRects(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+ if (sys->scaleProc && D3D11_UpscalerUsed(sys->scaleProc))
+ {
+ D3D11_UpscalerGetSize(sys->scaleProc, &sys->quad_fmt.i_width, &sys->quad_fmt.i_height);
+
+ sys->quad_fmt.i_x_offset = 0;
+ sys->quad_fmt.i_y_offset = 0;
+ sys->quad_fmt.i_visible_width = sys->quad_fmt.i_width;
+ sys->quad_fmt.i_visible_height = sys->quad_fmt.i_height;
+
+ sys->picQuad.i_width = sys->quad_fmt.i_width;
+ sys->picQuad.i_height = sys->quad_fmt.i_height;
+
+ UpdateRects(vd, NULL, true);
+ UpdateSize(vd);
+ }
+ else
+ {
+ UpdateRects(vd, NULL, true);
+ }
+}
+
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
@@ -935,14 +1016,26 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
{
picture_sys_t *p_sys = ActivePictureSys(picture);
+ D3D11_TEXTURE2D_DESC srcDesc;
+ ID3D11Texture2D_GetDesc(p_sys->texture[KNOWN_DXGI_INDEX], &srcDesc);
+
if (is_d3d11_opaque(picture->format.i_chroma))
d3d11_device_lock( &sys->d3d_dev );
+ if (sys->scaleProc && D3D11_UpscalerUsed(sys->scaleProc))
+ {
+ if (D3D11_UpscalerScale(VLC_OBJECT(vd), sys->scaleProc, p_sys) != VLC_SUCCESS)
+ return;
+ uint32_t witdh, height;
+ D3D11_UpscalerGetSize(sys->scaleProc, &witdh, &height);
+ srcDesc.Width = witdh;
+ srcDesc.Height = height;
+ }
+
if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader) {
- D3D11_TEXTURE2D_DESC srcDesc,texDesc;
+ D3D11_TEXTURE2D_DESC texDesc;
if (!is_d3d11_opaque(picture->format.i_chroma))
Direct3D11UnmapPoolTexture(picture);
- ID3D11Texture2D_GetDesc(p_sys->texture[KNOWN_DXGI_INDEX], &srcDesc);
ID3D11Texture2D_GetDesc(sys->stagingSys.texture[0], &texDesc);
D3D11_BOX box = {
.top = 0,
@@ -959,23 +1052,23 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
}
else
{
- D3D11_TEXTURE2D_DESC texDesc;
- ID3D11Texture2D_GetDesc(p_sys->texture[0], &texDesc);
- if (texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ if (srcDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
{
/* for performance reason we don't want to allocate this during
* display, do it preferrably when creating the texture */
assert(p_sys->resourceView[0]!=NULL);
}
- if ( sys->picQuad.i_height != texDesc.Height ||
- sys->picQuad.i_width != texDesc.Width )
+ if ( sys->picQuad.i_height != srcDesc.Height ||
+ sys->picQuad.i_width != srcDesc.Width )
{
/* the decoder produced different sizes than the vout, we need to
* adjust the vertex */
- sys->picQuad.i_height = texDesc.Height;
- sys->picQuad.i_width = texDesc.Width;
+ sys->quad_fmt.i_width = srcDesc.Width;
+ sys->quad_fmt.i_height = srcDesc.Height;
+ sys->picQuad.i_width = sys->quad_fmt.i_width;
+ sys->picQuad.i_height = sys->quad_fmt.i_height;
- UpdateRects(vd, NULL, true);
+ CallUpdateRects(vd);
UpdateSize(vd);
}
}
@@ -1023,7 +1116,14 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
/* Render the quad */
if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader)
D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad, sys->stagingSys.resourceView, sys->d3drenderTargetView);
- else {
+ else if (sys->scaleProc && D3D11_UpscalerUsed(sys->scaleProc))
+ {
+ ID3D11ShaderResourceView *SRV[D3D11_MAX_SHADER_VIEW];
+ D3D11_UpscalerGetSRV(sys->scaleProc, SRV);
+ D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad, SRV, sys->d3drenderTargetView);
+ }
+ else
+ {
picture_sys_t *p_sys = ActivePictureSys(picture);
D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad, p_sys->resourceView, sys->d3drenderTargetView);
}
@@ -1296,6 +1396,74 @@ static const d3d_format_t *GetBlendableFormat(vout_display_t *vd, vlc_fourcc_t i
return FindD3D11Format( vd, &vd->sys->d3d_dev, i_src_chroma, false, 0, 0, 0, false, supportFlags );
}
+static bool CanUseTextureArray(vout_display_t *vd)
+{
+#ifndef HAVE_ID3D11VIDEODECODER
+ (void) vd;
+ return false;
+#else
+ // 15.200.1062.1004 is wrong - 2015/08/03 - 15.7.1 WHQL
+ // 21.19.144.1281 is wrong -
+ // 22.19.165.3 is good - 2017/05/04 - ReLive Edition 17.5.1
+ struct wddm_version WDDM_os = {
+ .wddm = 21, // starting with drivers designed for W10 Anniversary Update
+ };
+ if (D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM_os) != VLC_SUCCESS)
+ {
+ msg_Dbg(vd, "AMD driver too old, fallback to legacy shader mode");
+ return false;
+ }
+
+ // xx.xx.1000.xxx drivers can't happen here for WDDM > 2.0
+ struct wddm_version WDDM_build = {
+ .revision = 162,
+ };
+ if (D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM_build) != VLC_SUCCESS)
+ {
+ msg_Dbg(vd, "Bogus AMD driver detected, fallback to legacy shader mode");
+ return false;
+ }
+
+ return true;
+#endif
+}
+
+static bool BogusZeroCopy(const vout_display_t *vd)
+{
+ if (vd->sys->d3d_dev.adapterDesc.VendorId != GPU_MANUFACTURER_AMD)
+ return false;
+
+ switch (vd->sys->d3d_dev.adapterDesc.DeviceId)
+ {
+ case 0x687F: // RX Vega 56/64
+ case 0x6863: // RX Vega Frontier Edition
+ case 0x15DD: // RX Vega 8/11 (Ryzen iGPU)
+ {
+ struct wddm_version WDDM = {
+ .revision = 14011, // 18.10.2 - 2018/06/11
+ };
+ return D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM) != VLC_SUCCESS;
+ }
+ default:
+ return false;
+ }
+}
+
+static void InitScaleProcessor(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+ if (sys->upscaleMode != upscale_VideoProcessor && sys->upscaleMode != upscale_SuperResolution)
+ return;
+
+ sys->scaleProc = D3D11_UpscalerCreate(VLC_OBJECT(vd), &sys->d3d_dev, sys->quad_fmt.i_chroma,
+ sys->upscaleMode == upscale_SuperResolution);
+ if (sys->scaleProc == NULL)
+ sys->upscaleMode = upscale_LinearSampler;
+
+ msg_Dbg(vd, "Using %s scaler", sys->upscaleMode != upscale_SuperResolution ?
+ "Video Processor": "Super Resolution");
+}
+
static int Direct3D11Open(vout_display_t *vd, bool external_device)
{
vout_display_sys_t *sys = vd->sys;
@@ -1378,6 +1546,47 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
return err;
}
+ char *psz_upscale = var_InheritString(vd, "d3d11-upscale-mode");
+ if (strcmp("linear", psz_upscale) == 0)
+ sys->upscaleMode = upscale_LinearSampler;
+ else if (strcmp("point", psz_upscale) == 0)
+ sys->upscaleMode = upscale_PointSampler;
+ else if (strcmp("processor", psz_upscale) == 0)
+ sys->upscaleMode = upscale_VideoProcessor;
+ else if (strcmp("super", psz_upscale) == 0)
+ sys->upscaleMode = upscale_SuperResolution;
+ else
+ {
+ msg_Warn(vd, "unknown upscale mode %s, using linear sampler", psz_upscale);
+ sys->upscaleMode = upscale_LinearSampler;
+ }
+ free(psz_upscale);
+
+ video_format_Init(&sys->quad_fmt, vd->source.i_chroma);
+ video_format_Copy(&sys->quad_fmt, &vd->source);
+ if (sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution)
+ sys->sys.src_fmt = &sys->quad_fmt;
+ InitScaleProcessor(vd);
+
+ video_format_Copy(&sys->pool_fmt, &fmt);
+
+ sys->legacy_shader = sys->d3d_dev.feature_level < D3D_FEATURE_LEVEL_10_0 ||
+ (sys->scaleProc == NULL && !CanUseTextureArray(vd)) ||
+ BogusZeroCopy(vd);
+
+ if (!sys->legacy_shader && is_d3d11_opaque(sys->pool_fmt.i_chroma))
+ {
+ sys->pool_fmt.i_width = (sys->pool_fmt.i_width + 0x7F) & ~0x7F;
+ sys->pool_fmt.i_height = (sys->pool_fmt.i_height + 0x7F) & ~0x7F;
+ }
+ else
+ if ( sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
+ sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
+ {
+ sys->pool_fmt.i_width = (sys->pool_fmt.i_width + 0x01) & ~0x01;
+ sys->pool_fmt.i_height = (sys->pool_fmt.i_height + 0x01) & ~0x01;
+ }
+
if (Direct3D11CreateGenericResources(vd)) {
msg_Err(vd, "Failed to allocate resources");
return VLC_EGENERIC;
@@ -1525,59 +1734,6 @@ static void UpdatePicQuadPosition(vout_display_t *vd)
#endif
}
-static bool CanUseTextureArray(vout_display_t *vd)
-{
-#ifndef HAVE_ID3D11VIDEODECODER
- (void) vd;
- return false;
-#else
- // 15.200.1062.1004 is wrong - 2015/08/03 - 15.7.1 WHQL
- // 21.19.144.1281 is wrong -
- // 22.19.165.3 is good - 2017/05/04 - ReLive Edition 17.5.1
- struct wddm_version WDDM_os = {
- .wddm = 21, // starting with drivers designed for W10 Anniversary Update
- };
- if (D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM_os) != VLC_SUCCESS)
- {
- msg_Dbg(vd, "AMD driver too old, fallback to legacy shader mode");
- return false;
- }
-
- // xx.xx.1000.xxx drivers can't happen here for WDDM > 2.0
- struct wddm_version WDDM_build = {
- .revision = 162,
- };
- if (D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM_build) != VLC_SUCCESS)
- {
- msg_Dbg(vd, "Bogus AMD driver detected, fallback to legacy shader mode");
- return false;
- }
-
- return true;
-#endif
-}
-
-static bool BogusZeroCopy(const vout_display_t *vd)
-{
- if (vd->sys->d3d_dev.adapterDesc.VendorId != GPU_MANUFACTURER_AMD)
- return false;
-
- switch (vd->sys->d3d_dev.adapterDesc.DeviceId)
- {
- case 0x687F: // RX Vega 56/64
- case 0x6863: // RX Vega Frontier Edition
- case 0x15DD: // RX Vega 8/11 (Ryzen iGPU)
- {
- struct wddm_version WDDM = {
- .revision = 14011, // 18.10.2 - 2018/06/11
- };
- return D3D11CheckDriverVersion(&vd->sys->d3d_dev, GPU_MANUFACTURER_AMD, &WDDM) != VLC_SUCCESS;
- }
- default:
- return false;
- }
-}
-
/* TODO : handle errors better
TODO : seperate out into smaller functions like createshaders */
static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_format_t *fmt)
@@ -1585,9 +1741,6 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
vout_display_sys_t *sys = vd->sys;
HRESULT hr;
- sys->legacy_shader = sys->d3d_dev.feature_level < D3D_FEATURE_LEVEL_10_0 || !CanUseTextureArray(vd) ||
- BogusZeroCopy(vd);
-
hr = D3D11_CompilePixelShader(vd, &sys->hd3d, sys->legacy_shader, &sys->d3d_dev,
sys->picQuad.formatInfo, &sys->display, fmt->transfer, fmt->primaries,
fmt->b_color_range_full,
@@ -1600,20 +1753,8 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
sys->picQuad.i_width = fmt->i_width;
sys->picQuad.i_height = fmt->i_height;
- if (!sys->legacy_shader && is_d3d11_opaque(fmt->i_chroma))
- {
- sys->picQuad.i_width = (sys->picQuad.i_width + 0x7F) & ~0x7F;
- sys->picQuad.i_height = (sys->picQuad.i_height + 0x7F) & ~0x7F;
- }
- else
- if ( sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
- sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
- {
- sys->picQuad.i_width = (sys->picQuad.i_width + 0x01) & ~0x01;
- sys->picQuad.i_height = (sys->picQuad.i_height + 0x01) & ~0x01;
- }
- UpdateRects(vd, NULL, true);
+ CallUpdateRects(vd);
#ifdef HAVE_ID3D11VIDEODECODER
if (!is_d3d11_opaque(fmt->i_chroma) || sys->legacy_shader)
@@ -1742,14 +1883,14 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
ID3D11DepthStencilState_Release(pDepthStencilState);
}
- UpdateRects(vd, NULL, true);
-
hr = UpdateBackBuffer(vd);
if (FAILED(hr)) {
msg_Err(vd, "Could not update the backbuffer. (hr=0x%lX)", hr);
return VLC_EGENERIC;
}
+ CallUpdateRects(vd);
+
if (sys->d3dregion_format != NULL)
{
hr = D3D11_CompilePixelShader(vd, &sys->hd3d, sys->legacy_shader, &sys->d3d_dev,
@@ -1823,6 +1964,7 @@ static void Direct3D11DestroyPool(vout_display_t *vd)
if (sys->sys.pool)
picture_pool_Release(sys->sys.pool);
sys->sys.pool = NULL;
+ video_format_Clean(&sys->pool_fmt);
}
static void Direct3D11DestroyResources(vout_display_t *vd)
@@ -1837,6 +1979,13 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
ReleasePictureSys(&sys->stagingSys);
+ if (sys->scaleProc != NULL)
+ {
+ D3D11_UpscalerDestroy(sys->scaleProc);
+ sys->scaleProc = NULL;
+ }
+ video_format_Clean(&sys->quad_fmt);
+
if (sys->pVertexLayout)
{
ID3D11InputLayout_Release(sys->pVertexLayout);
@@ -2027,12 +2176,18 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
d3d_quad_t *quad = (d3d_quad_t *) quad_picture->p_sys;
- quad->cropViewport.Width = (FLOAT) r->fmt.i_visible_width * RECTWidth(sys->sys.rect_dest) / subpicture->i_original_picture_width;
- quad->cropViewport.Height = (FLOAT) r->fmt.i_visible_height * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
+ vout_display_cfg_t place_cfg = *vd->cfg;
+ place_cfg.display.width = RECTWidth(sys->sys.rect_dest_clipped);
+ place_cfg.display.height = RECTHeight(sys->sys.rect_dest_clipped);
+ vout_display_place_t place;
+ vout_display_PlacePicture(&place, &vd->source, &place_cfg, false);
+
+ quad->cropViewport.Width = (FLOAT) r->fmt.i_visible_width * place.width / subpicture->i_original_picture_width;
+ quad->cropViewport.Height = (FLOAT) r->fmt.i_visible_height * place.height / subpicture->i_original_picture_height;
quad->cropViewport.MinDepth = 0.0f;
quad->cropViewport.MaxDepth = 1.0f;
- quad->cropViewport.TopLeftX = sys->sys.rect_dest.left + (FLOAT) r->i_x * RECTWidth(sys->sys.rect_dest) / subpicture->i_original_picture_width;
- quad->cropViewport.TopLeftY = sys->sys.rect_dest.top + (FLOAT) r->i_y * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
+ quad->cropViewport.TopLeftX = place.x + (FLOAT) r->i_x * place.width / subpicture->i_original_picture_width;
+ quad->cropViewport.TopLeftY = place.y + (FLOAT) r->i_y * place.height / subpicture->i_original_picture_height;
D3D11_UpdateQuadOpacity(vd, &sys->d3d_dev, quad, r->i_alpha / 255.0f );
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/70de1313be8e1d4bc90aeea6ea67a57db1924b05...56222b9290dd9bf08e02b10b1e9ee13d68931fc2
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/70de1313be8e1d4bc90aeea6ea67a57db1924b05...56222b9290dd9bf08e02b10b1e9ee13d68931fc2
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list