Browse Source

direct3d11: use NVIDIA super-resolution upscaler

Co-authored-by: Steve Lhomme <robux4@ycbcr.xyz>
pull/162/head
Chilledheart 3 years ago
committed by Steve Lhomme
parent
commit
beac9098db
  1. 61
      modules/video_output/win32/d3d11_scaler.cpp
  2. 2
      modules/video_output/win32/d3d11_scaler.h
  3. 19
      modules/video_output/win32/direct3d11.cpp

61
modules/video_output/win32/d3d11_scaler.cpp

@ -25,6 +25,8 @@ 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;
@ -41,8 +43,24 @@ static const d3d_format_t *GetDirectRenderingFormat(vlc_object_t *vd, d3d11_devi
return FindD3D11Format( vd, d3d_dev, i_src_chroma, DXGI_RGB_FORMAT|DXGI_YUV_FORMAT, 0, 0, 0, DXGI_CHROMA_GPU, supportFlags );
}
d3d11_scaler *D3D11_UpscalerCreate(vlc_object_t *vd, d3d11_device_t *d3d_dev, vlc_fourcc_t i_chroma)
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;
}
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)
{
@ -70,6 +88,7 @@ d3d11_scaler *D3D11_UpscalerCreate(vlc_object_t *vd, d3d11_device_t *d3d_dev, vl
}
scaleProc->d3d_fmt = fmt;
scaleProc->super_res = super_res;
return scaleProc;
error:
delete scaleProc;
@ -98,6 +117,7 @@ int D3D11_UpscalerUpdate(vlc_object_t *vd, d3d11_scaler *scaleProc, d3d11_device
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;
@ -229,8 +249,47 @@ int D3D11_UpscalerUpdate(vlc_object_t *vd, d3d11_scaler *scaleProc, d3d11_device
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;
}
}
}
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:

2
modules/video_output/win32/d3d11_scaler.h

@ -20,7 +20,7 @@ extern "C" {
struct d3d11_scaler;
struct d3d11_scaler *D3D11_UpscalerCreate(vlc_object_t *, d3d11_device_t*, vlc_fourcc_t i_chroma);
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 *,

19
modules/video_output/win32/direct3d11.cpp

@ -66,9 +66,9 @@ static void Close(vout_display_t *);
#define UPSCALE_MODE_LONGTEXT N_("Select the upscaling mode for video.")
static const char *const ppsz_upscale_mode[] = {
"linear", "point", "processor" };
"linear", "point", "processor", "super" };
static const char *const ppsz_upscale_mode_text[] = {
N_("Linear Sampler"), N_("Point Sampler"), N_("Video Processor") };
N_("Linear Sampler"), N_("Point Sampler"), N_("Video Processor"), N_("Super Resolution") };
vlc_module_begin ()
set_shortname("Direct3D11")
@ -90,6 +90,7 @@ enum d3d11_upscale
upscale_LinearSampler,
upscale_PointSampler,
upscale_VideoProcessor,
upscale_SuperResolution,
};
typedef struct vout_display_sys_t
@ -208,7 +209,7 @@ static int UpdateDisplayFormat(vout_display_t *vd, const video_format_t *fmt)
return VLC_EGENERIC;
}
if (sys->upscaleMode == upscale_VideoProcessor)
if (sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution)
{
D3D11_UpscalerUpdate(VLC_OBJECT(vd), sys->scaleProc, sys->d3d_dev,
vd->source, &sys->picQuad.quad_fmt, &vd->cfg->display);
@ -480,7 +481,7 @@ static int Control(vout_display_t *vd, int query)
{
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
if (sys->upscaleMode == upscale_VideoProcessor)
if (sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution)
{
D3D11_UpscalerUpdate(VLC_OBJECT(vd), sys->scaleProc, sys->d3d_dev,
vd->source, &sys->picQuad.quad_fmt, &vd->cfg->display);
@ -787,17 +788,19 @@ static const d3d_format_t *GetBlendableFormat(vout_display_t *vd, vlc_fourcc_t i
static void InitScaleProcessor(vout_display_t *vd)
{
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
if (sys->upscaleMode != upscale_VideoProcessor)
if (sys->upscaleMode != upscale_VideoProcessor && sys->upscaleMode != upscale_SuperResolution)
return;
sys->scaleProc = D3D11_UpscalerCreate(VLC_OBJECT(vd), sys->d3d_dev, sys->picQuad.quad_fmt.i_chroma);
sys->scaleProc = D3D11_UpscalerCreate(VLC_OBJECT(vd), sys->d3d_dev, sys->picQuad.quad_fmt.i_chroma,
sys->upscaleMode == upscale_SuperResolution);
if (sys->scaleProc == NULL)
{
msg_Dbg(vd, "forcing linear sampler");
sys->upscaleMode = upscale_LinearSampler;
}
msg_Dbg(vd, "Using Video Processor scaler");
msg_Dbg(vd, "Using %s scaler", sys->upscaleMode != upscale_SuperResolution ?
"Video Processor": "Super Resolution");
}
static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, vlc_video_context *vctx)
@ -857,6 +860,8 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, vlc_video_co
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);

Loading…
Cancel
Save