Skip to content
This repository

[windows] Enable shader based HQ scalers for DXVA renderer #838

Merged
merged 1 commit into from 8 months ago

8 participants

a11599 jmarshallnz CrystalP PKOneTwo da-anda Brannon King Martijn Kaijser Martin van Beurden
a11599
Collaborator

The patch enables pixel shader based scaling with DXVA rendering. This is practically a dusted down patch from CrystalP with an added GPU flush. The flush is required to prevent stuttering in ION (and possibly other cards). The impact on image quality depends on the GPU. Some do only bilinear even if they would have the ponies to do better; in those cases the quality improvement is very noticeable.

According to my tests, thanks to CrystalP's scaler speedup it can now do 1080p upscaling from any source up to 60 fps on the 40 shader Ati 3450 using 'optimized' scalers and tops out at ~45 fps using unoptimized ones. More powerful GPUs should do 60 fps even with unoptimized scalers easily.

By default, the DXVA renderer will default to DXVA scaling when scaling method is set to "Automatic" for a number of reasons (see in comments).

jmarshallnz
Owner

The settings nazi has to ask (without bothering to check the code in detail :p) whether it's reasonable to have the new setting. If it performs well enough on most hardware, why not just have it on? I presume the user can set it back to use whatever the DXVA default is anyway via the VideoOSD, right?

a11599
Collaborator

Good point. The setting comes from times before CrystalP's scaler speedup, so it is not really needed, so I will remove it. However, I would keep DXVA scaling as a default for automatic for three reasons:

  1. Ati drivers come out of the box with edge enhancement enabled. This was designed to work after scaling. So unless the user explicitly disables EE in CCC, our HQ scalers look worse than even DXVA bilinear (at least to me).
  2. There are some really weak GPUs out there (Intel HD) that have minuscule shader performance and cannot do any of our PS based scalers.
  3. Newer cards actually offer very good DXVA scaling. My HD 6570 does look like spline, it has a very nice sharp scaler with very little ringing. I expect this trend to continue. ;)

People preferring these scalers can just set their preferred one as a default for all videos and that's it. :)

a11599
Collaborator

Removed the setting. If there are no objections, I would like to merge this in the May window.

jmarshallnz
Owner

Looks good to me once squashed down - your thoughts @CrystalP

a11599
Collaborator

Rebased, tested and squashed, I think this is ready to go now.

xbmc/cores/VideoRenderers/WinRenderer.cpp
... ...
@@ -341,6 +341,19 @@ void CWinRenderer::Update(bool bPauseDrawing)
341 341
   ManageDisplay();
342 342
 }
343 343
 
  344
+void CWinRenderer::FlushGPU()
  345
+{
  346
+  LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
  347
+  IDirect3DQuery9* pEvent = NULL;
  348
+
  349
+  pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEvent);
  350
+  if (pEvent != NULL)
  351
+  {
  352
+    pEvent->Issue(D3DISSUE_END);
  353
+    while (S_FALSE == pEvent->GetData(NULL, 0, D3DGETDATA_FLUSH)) Sleep(1);
  354
+  }
  355
+}
1
CrystalP Collaborator
CrystalP added a note April 29, 2012

This method belongs to RenderSystemDX I think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
CrystalP
Collaborator

Changing the scaling method while viewing a video gives me a black screen for the HQ scalers.

The point of the patch was originally to help with the quality of the upscaling on the Ion (was like bilinear). But it stuttered once in a while, making the exercise pointless. Since other GPUs already have similar quality to the xbmc scalers, the patch didn't make sense to apply.

If you verified that the playback is 100% smooth on Ion thanks to the GPU flush, fine. The important frame rates are 24 and 25.
Did you try what happens with interlaced material? The scaler selection code has a fallback to bilinear that could bite us since there is no bilinear scaler implemented here.

CrystalP
Collaborator

More info: on ATI 4550 this works, on nVidia G210 (similar to Ion G2) it doesn't.

xbmc/cores/VideoRenderers/WinRenderer.cpp
... ...
@@ -456,7 +469,15 @@ bool CWinRenderer::CreateIntermediateRenderTarget()
456 469
 
457 470
   CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format);
458 471
 
459  
-  if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, format, D3DPOOL_DEFAULT))
  472
+  if (m_renderMethod == RENDER_DXVA)
  473
+  {
  474
+    if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT))
  475
+    {
  476
+      CLog::Log(LOGERROR, __FUNCTION__": Failed to create render target texture. Going back to DXVA hardware scaling.");
  477
+      return false;
  478
+    }
  479
+  }
  480
+  else if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, format, D3DPOOL_DEFAULT))
1
CrystalP Collaborator
CrystalP added a note April 29, 2012

Maybe clearer to have if (m_renderMethod = RENDER_DXVA) { new stuff} else { old stuff }
Or change the format selection to include the dxva case.

Would be nice to have the Log() just before log the actual format in the dxva case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
a11599
Collaborator
a11599 commented May 06, 2012

It worked originally on the ION and was 100% stutter free with the GPU flush (before the scaler speedup) for 24p/25p. I used it for months. Something must have happened in between that broke this on nVidia. Unfortunately I have no nVidia HW near me that makes it difficult to fix.

Agree with the rest of the comments, will do them, I need to adjust the patch anyways. If you have some suggestions on what to do to fix the nVidia issue that would be great.

Actually there are more GPUs that do awful scaling, Ati 3450, 3850 and 5145 are three examples (bilinear). So the patch might be beneficial for more people.

PKOneTwo

Just an FYI: using ATI 5450 and 6450. And the quality is more then visible (with patch integrated and) using Lanczos3 compared to DXVA setting!

PKOneTwo

Since i really love to have better quality then DXVA scaler (lanczos3 for example) i just edited the patch file, so it suits with the changes in master (lines, the one and the other changes of code):

http://pastebin.com/raw.php?i=qhSSYuQt
have fun

da-anda
Collaborator

any love left for this PR? Having PVR now some HQ scalers (and deinterlacers) would really be nice to have.

Martijn Kaijser

@a11599
care to update this PR?

a11599
Collaborator

Will do.

a11599
Collaborator

OK, here we go again. Rebased and adjusted code as @CrystalP requested. This is my last take on this subject. Please raise your concerns if any. I would be glad to receive test results too.

I tested progressive, interlaced, DXVA and software decoded video and have not found any problems but all my HW is ATI. Some more test results in this thread: http://forum.xbmc.org/showthread.php?tid=127174. I got reports from nV users (no black screen issue as reported by CrystalP).

Martijn Kaijser

@a11599
added test build including this patch in the forum thread.
Perhaps you could add to the thread what exactly needs testing (or perhaps start dedicated thread)
I have nvidia and an intel onboard GPU so i can do some testing as well. Played several video so far without problems

a11599
Collaborator

@MartijnKaijser thanks for the testing. I added details on what to look for in the forum thread.

a11599
Collaborator

Spotted a rebase problem which probably broke 3D playback.

a11599
Collaborator

Last call; based on the positive feedbacks I am about to squash down and merge this in the September window. @MartijnKaijser thanks for your help in arranging the testing.

a11599 a11599 merged commit 390def3 into from August 31, 2013
a11599 a11599 closed this August 31, 2013
a11599 a11599 deleted the branch August 31, 2013
Deleted user Unknown referenced this pull request from a commit October 18, 2013
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Sep 01, 2013
a11599 [win32][added] Shader based HQ scalers for DXVA renderer 3c31288
This page is out of date. Refresh to see the latest.
60  xbmc/cores/VideoRenderers/WinRenderer.cpp
@@ -445,7 +445,8 @@ bool CWinRenderer::CreateIntermediateRenderTarget()
445 445
   D3DFORMAT format = D3DFMT_X8R8G8B8;
446 446
   DWORD usage = D3DUSAGE_RENDERTARGET;
447 447
 
448  
-  if      (g_Windowing.IsTextureFormatOk(D3DFMT_A2R10G10B10, usage)) format = D3DFMT_A2R10G10B10;
  448
+  if      (m_renderMethod == RENDER_DXVA)                            format = D3DFMT_X8R8G8B8;
  449
+  else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2R10G10B10, usage)) format = D3DFMT_A2R10G10B10;
449 450
   else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2B10G10R10, usage)) format = D3DFMT_A2B10G10R10;
450 451
   else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8R8G8B8, usage))    format = D3DFMT_A8R8G8B8;
451 452
   else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8B8G8R8, usage))    format = D3DFMT_A8B8G8R8;
@@ -525,7 +526,12 @@ void CWinRenderer::SelectPSVideoFilter()
525 526
     bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth();
526 527
     bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f);
527 528
 
528  
-    if (scaleSD && scaleUp && scaleFps && Supports(VS_SCALINGMETHOD_LANCZOS3_FAST))
  529
+    if (m_renderMethod == RENDER_DXVA)
  530
+    {
  531
+      m_scalingMethod = VS_SCALINGMETHOD_DXVA_HARDWARE;
  532
+      m_bUseHQScaler = false;
  533
+    }
  534
+    else if (scaleSD && scaleUp && scaleFps && Supports(VS_SCALINGMETHOD_LANCZOS3_FAST))
529 535
     {
530 536
       m_scalingMethod = VS_SCALINGMETHOD_LANCZOS3_FAST;
531 537
       m_bUseHQScaler = true;
@@ -573,6 +579,10 @@ void CWinRenderer::UpdatePSVideoFilter()
573 579
 
574 580
   SAFE_DELETE(m_colorShader);
575 581
 
  582
+  // When using DXVA, we are already setup at this point, color shader is not needed
  583
+  if (m_renderMethod == RENDER_DXVA)
  584
+    return;
  585
+
576 586
   if (m_bUseHQScaler)
577 587
   {
578 588
     m_colorShader = new CYUV2RGBShader();
@@ -618,14 +628,11 @@ void CWinRenderer::UpdateVideoFilter()
618 628
     break;
619 629
 
620 630
   case RENDER_PS:
  631
+  case RENDER_DXVA:
621 632
     SelectPSVideoFilter();
622 633
     UpdatePSVideoFilter();
623 634
     break;
624 635
 
625  
-  case RENDER_DXVA:
626  
-    // Everything already setup, nothing to do.
627  
-    break;
628  
-
629 636
   default:
630 637
     return;
631 638
   }
@@ -635,6 +642,9 @@ void CWinRenderer::Render(DWORD flags)
635 642
 {
636 643
   if (m_renderMethod == RENDER_DXVA)
637 644
   {
  645
+    UpdateVideoFilter();
  646
+    if (m_bUseHQScaler)
  647
+      g_Windowing.FlushGPU();
638 648
     CWinRenderer::RenderProcessor(flags);
639 649
     return;
640 650
   }
@@ -918,19 +928,38 @@ void CWinRenderer::RenderProcessor(DWORD flags)
918 928
 {
919 929
   CSingleLock lock(g_graphicsContext);
920 930
   HRESULT hr;
  931
+  CRect destRect;
  932
+
  933
+  if (m_bUseHQScaler)
  934
+  {
  935
+    destRect.y1 = 0.0f;
  936
+    destRect.y2 = m_sourceHeight;
  937
+    destRect.x1 = 0.0f;
  938
+    destRect.x2 = m_sourceWidth;
  939
+  }
  940
+  else
  941
+    destRect = m_destRect;
921 942
 
922 943
   DXVABuffer *image = (DXVABuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
923 944
 
924 945
   IDirect3DSurface9* target;
925  
-  if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
  946
+  if (m_bUseHQScaler)
  947
+    m_IntermediateTarget.GetSurfaceLevel(0, &target);
  948
+  else
926 949
   {
927  
-    CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
928  
-    return;
  950
+    if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
  951
+    {
  952
+      CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
  953
+      return;
  954
+    }
929 955
   }
930 956
 
931  
-  m_processor.Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect), target, image->id, flags);
  957
+  m_processor.Render(m_sourceRect, g_graphicsContext.StereoCorrection(destRect), target, image->id, flags);
932 958
 
933 959
   target->Release();
  960
+
  961
+  if (m_bUseHQScaler)
  962
+    Stage2();
934 963
 }
935 964
 
936 965
 bool CWinRenderer::RenderCapture(CRenderCapture* capture)
@@ -1068,17 +1097,14 @@ bool CWinRenderer::Supports(ERENDERFEATURE feature)
1068 1097
 
1069 1098
 bool CWinRenderer::Supports(ESCALINGMETHOD method)
1070 1099
 {
1071  
-  if (m_renderMethod == RENDER_DXVA)
  1100
+  if (m_renderMethod == RENDER_PS || m_renderMethod == RENDER_DXVA)
1072 1101
   {
1073  
-    if(method == VS_SCALINGMETHOD_DXVA_HARDWARE)
  1102
+    if(m_renderMethod == RENDER_DXVA && method == VS_SCALINGMETHOD_DXVA_HARDWARE)
1074 1103
       return true;
1075  
-    return false;
1076  
-  }
1077  
-  else if(m_renderMethod == RENDER_PS)
1078  
-  {
  1104
+
1079 1105
     if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0)
1080 1106
     && (   method == VS_SCALINGMETHOD_AUTO
1081  
-        || method == VS_SCALINGMETHOD_LINEAR))
  1107
+       || (method == VS_SCALINGMETHOD_LINEAR && m_renderMethod == RENDER_PS) ))
1082 1108
         return true;
1083 1109
 
1084 1110
     if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
12  xbmc/rendering/dx/RenderSystemDX.cpp
@@ -1043,5 +1043,17 @@ bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode) const
1043 1043
   }
1044 1044
 }
1045 1045
 
  1046
+void CRenderSystemDX::FlushGPU()
  1047
+{
  1048
+  IDirect3DQuery9* pEvent = NULL;
  1049
+
  1050
+  m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEvent);
  1051
+  if (pEvent != NULL)
  1052
+  {
  1053
+    pEvent->Issue(D3DISSUE_END);
  1054
+    while (S_FALSE == pEvent->GetData(NULL, 0, D3DGETDATA_FLUSH))
  1055
+      Sleep(1);
  1056
+  }
  1057
+}
1046 1058
 
1047 1059
 #endif
2  xbmc/rendering/dx/RenderSystemDX.h
@@ -78,6 +78,8 @@ class CRenderSystemDX : public CRenderSystemBase
78 78
 
79 79
   virtual void Project(float &x, float &y, float &z);
80 80
 
  81
+  void FlushGPU();
  82
+
81 83
   LPDIRECT3DDEVICE9 Get3DDevice() { return m_pD3DDevice; }
82 84
   int GetBackbufferCount() const { return m_D3DPP.BackBufferCount; }
83 85
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.