[Windows] Move DX::GetErrorDescription to WIN32Util
[xbmc.git] / xbmc / cores / VideoPlayer / VideoRenderers / HwDecRender / DXVAHD.cpp
blob7c746cc6fb6439838c089afb16b46e70ff6209d9
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 // setting that here because otherwise SampleFormat is defined to AVSampleFormat
10 // which we don't use here
11 #define FF_API_OLD_SAMPLE_FMT 0
12 #define DEFAULT_STREAM_INDEX (0)
14 #include "DXVAHD.h"
16 #include "VideoRenderers/RenderFlags.h"
17 #include "VideoRenderers/RenderManager.h"
18 #include "VideoRenderers/windows/RendererBase.h"
19 #include "VideoRenderers/windows/RendererDXVA.h"
20 #include "rendering/dx/RenderContext.h"
21 #include "utils/StringUtils.h"
22 #include "utils/log.h"
24 #include "platform/win32/WIN32Util.h"
26 #include <mutex>
28 #include <Windows.h>
29 #include <d3d11_4.h>
30 #include <dxgi1_5.h>
32 using namespace DXVA;
33 using namespace Microsoft::WRL;
35 namespace
37 // magic constants taken from Chromium:
38 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/gl/swap_chain_presenter.cc#180
39 constexpr GUID GUID_INTEL_VPE_INTERFACE = {
40 0xedd1d4b9, 0x8659, 0x4cbc, {0xa4, 0xd6, 0x98, 0x31, 0xa2, 0x16, 0x3a, 0xc3}};
42 constexpr UINT kIntelVpeFnVersion = 0x01;
43 constexpr UINT kIntelVpeFnMode = 0x20;
44 constexpr UINT kIntelVpeFnScaling = 0x37;
45 constexpr UINT kIntelVpeVersion3 = 0x0003;
46 constexpr UINT kIntelVpeModePreproc = 0x01;
47 constexpr UINT kIntelVpeScalingSuperResolution = 0x2;
49 constexpr GUID GUID_NVIDIA_PPE_INTERFACE = {
50 0xd43ce1b3, 0x1f4b, 0x48ac, {0xba, 0xee, 0xc3, 0xc2, 0x53, 0x75, 0xe6, 0xf7}};
52 constexpr UINT kStreamExtensionVersionV1 = 0x1;
53 constexpr UINT kStreamExtensionMethodSuperResolution = 0x2;
54 } // unnamed namespace
56 struct DXVA::ProcColorSpaces
58 DXGI_COLOR_SPACE_TYPE inputColorSpace;
59 DXGI_COLOR_SPACE_TYPE outputColorSpace;
62 CProcessorHD::CProcessorHD()
64 DX::Windowing()->Register(this);
67 CProcessorHD::~CProcessorHD()
69 DX::Windowing()->Unregister(this);
70 UnInit();
73 void CProcessorHD::UnInit()
75 std::unique_lock<CCriticalSection> lock(m_section);
76 m_enumerator = nullptr;
77 Close();
80 void CProcessorHD::Close()
82 std::unique_lock<CCriticalSection> lock(m_section);
83 m_pVideoProcessor = nullptr;
84 m_pVideoContext = nullptr;
85 m_pVideoDevice = nullptr;
86 m_superResolutionEnabled = false;
87 m_configured = false;
90 bool CProcessorHD::InitProcessor()
92 HRESULT hr{};
93 m_pVideoDevice = nullptr;
94 m_pVideoContext = nullptr;
96 ComPtr<ID3D11DeviceContext1> pD3DDeviceContext = DX::DeviceResources::Get()->GetImmediateContext();
97 ComPtr<ID3D11Device> pD3DDevice = DX::DeviceResources::Get()->GetD3DDevice();
99 if (FAILED(hr = pD3DDeviceContext.As(&m_pVideoContext)))
101 CLog::LogF(LOGWARNING, "video context initialization is failed. Error {}",
102 CWIN32Util::FormatHRESULT(hr));
103 return false;
105 if (FAILED(hr = pD3DDevice.As(&m_pVideoDevice)))
107 CLog::LogF(LOGWARNING, "video device initialization is failed. Error {}",
108 CWIN32Util::FormatHRESULT(hr));
109 return false;
112 if (!m_enumerator)
113 return false;
115 m_procCaps = m_enumerator->ProbeProcessorCaps();
116 if (!m_procCaps.m_valid)
117 return false;
119 return true;
122 bool CProcessorHD::CheckFormats() const
124 if (!m_isValidConversion)
125 return true;
127 // check default output format (as render target)
128 return m_enumerator && m_enumerator->IsFormatSupportedOutput(m_conversion.m_outputFormat);
131 bool CProcessorHD::Open(const VideoPicture& picture,
132 std::shared_ptr<DXVA::CEnumeratorHD> enumerator)
134 Close();
136 std::unique_lock<CCriticalSection> lock(m_section);
138 m_color_primaries = picture.color_primaries;
139 m_color_transfer = picture.color_transfer;
140 m_enumerator = enumerator;
142 if (!InitProcessor())
143 return false;
145 return OpenProcessor();
148 bool CProcessorHD::ReInit()
150 std::unique_lock<CCriticalSection> lock(m_section);
151 Close();
153 if (!InitProcessor())
154 return false;
156 if (!CheckFormats())
157 return false;
159 return true;
162 bool CProcessorHD::OpenProcessor()
164 std::unique_lock<CCriticalSection> lock(m_section);
166 if ((!m_pVideoDevice || !m_pVideoContext || !m_enumerator || !m_procCaps.m_valid) && !ReInit())
168 CLog::LogF(LOGDEBUG, "invalid state, failed to re-initialize.");
169 return false;
172 CLog::LogF(LOGDEBUG, "creating processor.");
174 // create processor
175 m_pVideoProcessor = m_enumerator->CreateVideoProcessor(m_procCaps.m_procIndex);
177 if (!m_pVideoProcessor)
179 CLog::LogF(LOGDEBUG, "failed creating video processor.");
180 return false;
183 m_pVideoContext->VideoProcessorSetStreamAutoProcessingMode(m_pVideoProcessor.Get(), 0, FALSE);
184 m_pVideoContext->VideoProcessorSetStreamOutputRate(
185 m_pVideoProcessor.Get(), 0, D3D11_VIDEO_PROCESSOR_OUTPUT_RATE_NORMAL, FALSE, 0);
187 ComPtr<ID3D11VideoContext1> videoCtx1;
188 if (SUCCEEDED(m_pVideoContext.As(&videoCtx1)))
190 videoCtx1->VideoProcessorSetOutputShaderUsage(m_pVideoProcessor.Get(), 1);
192 else
194 CLog::LogF(LOGWARNING, "unable to retrieve ID3D11VideoContext1 to allow usage of shaders on "
195 "video processor output surfaces.");
198 // Output background color (black)
199 D3D11_VIDEO_COLOR color;
200 color.YCbCr = { 0.0625f, 0.5f, 0.5f, 1.0f }; // black color
201 m_pVideoContext->VideoProcessorSetOutputBackgroundColor(m_pVideoProcessor.Get(), TRUE, &color);
203 // AMD/HDR (as of 2023-06-16): processor tone maps by default and modifies high code values
204 // We want "passthrough" of the signal and to do our own tone mapping when needed.
205 // Disable the functionality by pretending that the display supports all PQ levels (0-10000)
206 const DXGI_ADAPTER_DESC ad = DX::DeviceResources::Get()->GetAdapterDesc();
207 bool streamIsHDR =
208 (m_color_primaries == AVCOL_PRI_BT2020) &&
209 (m_color_transfer == AVCOL_TRC_SMPTE2084 || m_color_transfer == AVCOL_TRC_ARIB_STD_B67);
211 if (m_procCaps.m_hasMetadataHDR10Support && ad.VendorId == PCIV_AMD && streamIsHDR)
213 ComPtr<ID3D11VideoContext2> videoCtx2;
214 if (SUCCEEDED(m_pVideoContext.As(&videoCtx2)))
216 DXGI_HDR_METADATA_HDR10 hdr10{};
217 hdr10.MaxMasteringLuminance = 10000;
218 hdr10.MinMasteringLuminance = 0;
220 videoCtx2->VideoProcessorSetOutputHDRMetaData(m_pVideoProcessor.Get(),
221 DXGI_HDR_METADATA_TYPE_HDR10,
222 sizeof(DXGI_HDR_METADATA_HDR10), &hdr10);
224 CLog::LogF(LOGDEBUG, "video processor tone mapping disabled.");
226 else
228 CLog::LogF(LOGDEBUG,
229 "unable to retrieve ID3D11VideoContext2 to disable video processor tone mapping.");
233 return true;
236 void CProcessorHD::ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER filter, int value, int min, int max, int def) const
238 if (filter >= static_cast<D3D11_VIDEO_PROCESSOR_FILTER>(NUM_FILTERS))
239 return;
241 // Unsupported filter. Ignore.
242 if (!m_procCaps.m_Filters[filter].bSupported)
243 return;
245 D3D11_VIDEO_PROCESSOR_FILTER_RANGE range = m_procCaps.m_Filters[filter].Range;
246 int val;
248 if(value > def)
249 val = range.Default + (range.Maximum - range.Default) * (value - def) / (max - def);
250 else if(value < def)
251 val = range.Default + (range.Minimum - range.Default) * (value - def) / (min - def);
252 else
253 val = range.Default;
255 m_pVideoContext->VideoProcessorSetStreamFilter(m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX, filter, val != range.Default, val);
258 ComPtr<ID3D11VideoProcessorInputView> CProcessorHD::GetInputView(CRenderBuffer* view) const
260 if (m_enumerator)
262 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC vpivd = {0, D3D11_VPIV_DIMENSION_TEXTURE2D, {0, 0}};
264 ComPtr<ID3D11Resource> resource;
265 unsigned arrayIdx = 0;
266 HRESULT hr = view->GetResource(resource.GetAddressOf(), &arrayIdx);
267 if (SUCCEEDED(hr))
269 vpivd.Texture2D.ArraySlice = arrayIdx;
270 return m_enumerator->CreateVideoProcessorInputView(resource.Get(), &vpivd);
273 return {};
276 bool CProcessorHD::CheckVideoParameters(const CRect& src,
277 const CRect& dst,
278 const UINT& rotation,
279 const float& contrast,
280 const float& brightness,
281 const CRenderBuffer& rb)
283 bool updatedParameter{false};
285 if (!m_configured || m_lastSrc != src)
287 const RECT sourceRECT = {static_cast<LONG>(src.x1), static_cast<LONG>(src.y1),
288 static_cast<LONG>(src.x2), static_cast<LONG>(src.y2)};
290 m_pVideoContext->VideoProcessorSetStreamSourceRect(m_pVideoProcessor.Get(),
291 DEFAULT_STREAM_INDEX, TRUE, &sourceRECT);
292 m_lastSrc = src;
293 updatedParameter = true;
296 if (!m_configured || m_lastDst != dst)
298 const RECT dstRECT = {static_cast<LONG>(dst.x1), static_cast<LONG>(dst.y1),
299 static_cast<LONG>(dst.x2), static_cast<LONG>(dst.y2)};
301 m_pVideoContext->VideoProcessorSetStreamDestRect(m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX,
302 TRUE, &dstRECT);
303 m_pVideoContext->VideoProcessorSetOutputTargetRect(m_pVideoProcessor.Get(), TRUE, &dstRECT);
305 m_lastDst = dst;
306 updatedParameter = true;
309 if (!m_configured || m_lastBrightness != brightness)
311 ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_BRIGHTNESS, static_cast<int>(brightness), 0, 100, 50);
313 m_lastBrightness = brightness;
314 updatedParameter = true;
317 if (!m_configured || m_lastContrast != contrast)
319 ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_CONTRAST, static_cast<int>(contrast), 0, 100, 50);
321 m_lastContrast = contrast;
322 updatedParameter = true;
325 // unused filters - set once and forget
326 if (!m_configured)
328 ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_HUE, 50, 0, 100, 50);
329 ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_SATURATION, 50, 0, 100, 50);
332 if (!m_configured || m_lastRotation != rotation)
334 m_pVideoContext->VideoProcessorSetStreamRotation(
335 m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX, rotation != 0,
336 static_cast<D3D11_VIDEO_PROCESSOR_ROTATION>(rotation / 90));
338 m_lastRotation = rotation;
339 updatedParameter = true;
342 ComPtr<ID3D11VideoContext1> videoCtx1;
343 if (SUCCEEDED(m_pVideoContext.As(&videoCtx1)))
345 if (!m_configured || m_lastConversion != m_conversion)
347 videoCtx1->VideoProcessorSetStreamColorSpace1(m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX,
348 m_conversion.m_inputCS);
349 videoCtx1->VideoProcessorSetOutputColorSpace1(m_pVideoProcessor.Get(),
350 m_conversion.m_outputCS);
352 m_lastConversion = m_conversion;
353 updatedParameter = true;
356 else if (!m_configured || m_lastColorSpace != rb.color_space || m_lastFullRange != rb.full_range)
358 // input colorspace
359 bool isBT601 = rb.color_space == AVCOL_SPC_BT470BG || rb.color_space == AVCOL_SPC_SMPTE170M;
360 // clang-format off
361 D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace
363 0u, // 0 - Playback, 1 - Processing
364 rb.full_range ? 0u : 1u, // 0 - Full (0-255), 1 - Limited (16-235) (RGB)
365 isBT601 ? 1u : 0u, // 0 - BT.601, 1 - BT.709
366 0u, // 0 - Conventional YCbCr, 1 - xvYCC
367 rb.full_range ? 2u : 1u // 0 - driver defaults, 2 - Full range [0-255], 1 - Studio range [16-235] (YUV)
369 // clang-format on
370 m_pVideoContext->VideoProcessorSetStreamColorSpace(m_pVideoProcessor.Get(),
371 DEFAULT_STREAM_INDEX, &colorSpace);
372 // Output color space
373 // don't apply any color range conversion, this will be fixed at later stage.
374 colorSpace.Usage = 0; // 0 - playback, 1 - video processing
375 colorSpace.RGB_Range = DX::Windowing()->UseLimitedColor() ? 1 : 0; // 0 - 0-255, 1 - 16-235
376 colorSpace.YCbCr_Matrix = 1; // 0 - BT.601, 1 = BT.709
377 colorSpace.YCbCr_xvYCC = 1; // 0 - Conventional YCbCr, 1 - xvYCC
378 colorSpace.Nominal_Range = 0; // 2 - 0-255, 1 = 16-235, 0 - undefined
379 m_pVideoContext->VideoProcessorSetOutputColorSpace(m_pVideoProcessor.Get(), &colorSpace);
381 m_lastColorSpace = rb.color_space;
382 m_lastFullRange = rb.full_range;
383 updatedParameter = true;
386 return updatedParameter;
389 bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, CRenderBuffer** views, DWORD flags, UINT frameIdx, UINT rotation, float contrast, float brightness)
391 std::unique_lock<CCriticalSection> lock(m_section);
393 // restore processor if it was lost
394 if (!m_pVideoProcessor && !OpenProcessor())
395 return false;
397 if (!views[2])
398 return false;
400 const bool updatedParam =
401 CheckVideoParameters(src, dst, rotation, contrast, brightness, *views[2]);
403 D3D11_VIDEO_FRAME_FORMAT dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
405 if ((flags & RENDER_FLAG_FIELD0) && (flags & RENDER_FLAG_TOP))
406 dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
407 else if ((flags & RENDER_FLAG_FIELD1) && (flags & RENDER_FLAG_BOT))
408 dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
409 else if ((flags & RENDER_FLAG_FIELD0) && (flags & RENDER_FLAG_BOT))
410 dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST;
411 else if ((flags & RENDER_FLAG_FIELD1) && (flags & RENDER_FLAG_TOP))
412 dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST;
414 m_pVideoContext->VideoProcessorSetStreamFrameFormat(m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX,
415 dxvaFrameFormat);
417 D3D11_VIDEO_PROCESSOR_STREAM stream_data = {};
418 stream_data.Enable = TRUE;
420 const bool frameProgressive = dxvaFrameFormat == D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
422 // Progressive or Interlaced video at normal rate.
423 const bool secondField = ((flags & RENDER_FLAG_FIELD1) && !frameProgressive) ? 1 : 0;
424 stream_data.InputFrameOrField = frameIdx + (secondField ? 1 : 0);
425 stream_data.OutputIndex = secondField;
427 // Render() gets called once for each displayed frame, following the pattern necessary to adapt
428 // the source fps to the display fps, with repetitions as needed (ex. 3:2 for 23.98fps at 59Hz)
429 // However there is no need to render the same frame more than once, the intermediate target is
430 // not cleared and the output of the previous processing is still there.
431 // For nVidia deinterlacing it's more than an optimization. The processor must see each field
432 // only once or it won't switch from bob to a more advanced algorithm.
433 // for ex. when playing 25i at 60fps, decoded frames A B => output A0 A1 B0 B1 B1
434 // B1 field is repeated and the second B1 must be skipped.
435 // Exception: always process when a parameter changes to provide immediate feedback to the user
437 if (m_configured && m_lastInputFrameOrField == stream_data.InputFrameOrField &&
438 m_lastOutputIndex == stream_data.OutputIndex && !updatedParam)
439 return true;
441 m_lastInputFrameOrField = stream_data.InputFrameOrField;
442 m_lastOutputIndex = stream_data.OutputIndex;
444 unsigned int providedPast = 0;
445 for (int i = 3; i < 8; i++)
447 if (views[i])
448 providedPast++;
450 unsigned int providedFuture = 0;
451 for (int i = 1; i >= 0; i--)
453 if (views[i])
454 providedFuture++;
456 const int futureFrames = std::min(providedFuture, m_procCaps.m_rateCaps.FutureFrames);
457 const int pastFrames = std::min(providedPast, m_procCaps.m_rateCaps.PastFrames);
458 std::vector<ID3D11VideoProcessorInputView*> pastViews(pastFrames, nullptr);
459 std::vector<ID3D11VideoProcessorInputView*> futureViews(futureFrames, nullptr);
461 stream_data.PastFrames = pastFrames;
462 stream_data.FutureFrames = futureFrames;
463 stream_data.ppPastSurfaces = pastViews.data();
464 stream_data.ppFutureSurfaces = futureViews.data();
466 std::vector<ComPtr<ID3D11VideoProcessorInputView>> all_views;
467 const int start = 2 - futureFrames;
468 const int end = 2 + pastFrames;
469 int count = 0;
471 for (int i = start; i <= end; i++)
473 if (!views[i])
474 continue;
476 ComPtr<ID3D11VideoProcessorInputView> view = GetInputView(views[i]);
478 if (i > 2)
480 // frames order should be { ?, T-3, T-2, T-1 }
481 pastViews[2 + pastFrames - i] = view.Get();
483 else if (i == 2)
485 stream_data.pInputSurface = view.Get();
487 else if (i < 2)
489 // frames order should be { T+1, T+2, T+3, .. }
490 futureViews[1 - i] = view.Get();
492 if (view)
494 count++;
495 all_views.push_back(view);
499 if (count != pastFrames + futureFrames + 1)
501 CLog::LogF(LOGERROR, "incomplete views set.");
502 return false;
505 // create output view for surface.
506 const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputViewDesc = {D3D11_VPOV_DIMENSION_TEXTURE2D,
507 {0}};
508 ComPtr<ID3D11VideoProcessorOutputView> pOutputView =
509 m_enumerator->CreateVideoProcessorOutputView(target, &outputViewDesc);
511 HRESULT hr{};
512 if (pOutputView)
514 hr = m_pVideoContext->VideoProcessorBlt(m_pVideoProcessor.Get(), pOutputView.Get(), 0, 1,
515 &stream_data);
516 if (S_OK != hr)
518 CLog::LogF(FAILED(hr) ? LOGERROR : LOGWARNING,
519 "VideoProcessorBlt returned {} while VideoProcessorBlt execution.",
520 CWIN32Util::FormatHRESULT(hr));
524 if (!m_configured)
525 m_configured = true;
527 return pOutputView && !FAILED(hr);
530 bool CProcessorHD::IsSuperResolutionSuitable(const VideoPicture& picture)
532 if (picture.iWidth > 1920)
533 return false;
535 const UINT outputWidth = DX::Windowing()->GetBackBuffer().GetWidth();
537 if (outputWidth <= picture.iWidth)
538 return false;
540 if (picture.color_primaries == AVCOL_PRI_BT2020 ||
541 picture.color_transfer == AVCOL_TRC_SMPTE2084 ||
542 picture.color_transfer == AVCOL_TRC_ARIB_STD_B67)
543 return false;
545 return true;
548 void CProcessorHD::TryEnableVideoSuperResolution()
550 if (!m_pVideoContext || !m_pVideoProcessor)
551 return;
553 const DXGI_ADAPTER_DESC ad = DX::DeviceResources::Get()->GetAdapterDesc();
555 if (ad.VendorId == PCIV_Intel)
557 EnableIntelVideoSuperResolution();
559 else if (ad.VendorId == PCIV_NVIDIA)
561 EnableNvidiaRTXVideoSuperResolution();
565 void CProcessorHD::EnableIntelVideoSuperResolution()
567 UINT param = 0;
569 struct IntelVpeExt
571 UINT function;
572 void* param;
575 IntelVpeExt ext{0, &param};
577 ext.function = kIntelVpeFnVersion;
578 param = kIntelVpeVersion3;
580 HRESULT hr = m_pVideoContext->VideoProcessorSetOutputExtension(
581 m_pVideoProcessor.Get(), &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
582 if (FAILED(hr))
584 CLog::LogF(LOGWARNING, "Failed to set the Intel VPE version with error {}.",
585 CWIN32Util::FormatHRESULT(hr));
586 return;
589 ext.function = kIntelVpeFnMode;
590 param = kIntelVpeModePreproc;
592 hr = m_pVideoContext->VideoProcessorSetOutputExtension(
593 m_pVideoProcessor.Get(), &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
594 if (FAILED(hr))
596 CLog::LogF(LOGWARNING, "Failed to set the Intel VPE mode with error {}.",
597 CWIN32Util::FormatHRESULT(hr));
598 return;
601 ext.function = kIntelVpeFnScaling;
602 param = kIntelVpeScalingSuperResolution;
604 hr = m_pVideoContext->VideoProcessorSetStreamExtension(
605 m_pVideoProcessor.Get(), 0, &GUID_INTEL_VPE_INTERFACE, sizeof(ext), &ext);
606 if (FAILED(hr))
608 CLog::LogF(LOGWARNING, "Failed to set the Intel VPE scaling type with error {}.",
609 CWIN32Util::FormatHRESULT(hr));
610 return;
613 CLog::LogF(LOGINFO, "Intel Video Super Resolution request enable successfully");
614 m_superResolutionEnabled = true;
617 void CProcessorHD::EnableNvidiaRTXVideoSuperResolution()
619 struct NvidiaStreamExt
621 UINT version;
622 UINT method;
623 UINT enable;
626 NvidiaStreamExt ext = {kStreamExtensionVersionV1, kStreamExtensionMethodSuperResolution, 1u};
628 HRESULT hr = m_pVideoContext->VideoProcessorSetStreamExtension(
629 m_pVideoProcessor.Get(), 0, &GUID_NVIDIA_PPE_INTERFACE, sizeof(ext), &ext);
630 if (FAILED(hr))
632 CLog::LogF(LOGWARNING, "Failed to set the NVIDIA video process stream extension with error {}.",
633 CWIN32Util::FormatHRESULT(hr));
634 return;
637 CLog::LogF(LOGINFO, "RTX Video Super Resolution request enable successfully");
638 m_superResolutionEnabled = true;
641 bool CProcessorHD::SetConversion(const ProcessorConversion& conversion)
643 std::unique_lock<CCriticalSection> lock(m_section);
645 if (!m_enumerator)
646 return false;
648 if (!m_enumerator || !m_enumerator->IsFormatSupportedInput(conversion.m_inputFormat) ||
649 !m_enumerator->IsFormatSupportedOutput(conversion.m_outputFormat))
650 return false;
652 if (m_enumerator->IsEnumerator1Available() &&
653 !m_enumerator->CheckConversion(conversion.m_inputFormat, conversion.m_inputCS,
654 conversion.m_outputFormat, conversion.m_outputCS))
656 CLog::LogF(LOGERROR, "Conversion {} is not supported", conversion.ToString());
657 return false;
660 m_conversion = conversion;
661 m_isValidConversion = true;
663 return true;
666 bool CProcessorHD::Supports(ERENDERFEATURE feature) const
668 switch (feature)
670 case RENDERFEATURE_BRIGHTNESS:
671 return m_procCaps.m_Filters[D3D11_VIDEO_PROCESSOR_FILTER_BRIGHTNESS].bSupported;
672 case RENDERFEATURE_CONTRAST:
673 return m_procCaps.m_Filters[D3D11_VIDEO_PROCESSOR_FILTER_CONTRAST].bSupported;
674 case RENDERFEATURE_ROTATION:
675 return (m_procCaps.m_vcaps.FeatureCaps & D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ROTATION);
676 default:
677 return false;