Aleksoid1978 / VideoRenderer

Внешний видео-рендерер
GNU General Public License v3.0
1.03k stars 115 forks source link

Fallback scaling method for when shaders are not working #36

Closed clsid2 closed 2 years ago

clsid2 commented 2 years ago

I was investigating a crash when running on Windows 11 inside a virtual machine.

This fixes that crash:

@@ -1987,6 +1987,11 @@ void CDX9VideoProcessor::UpdatePostScaleTexures()
        numPostScaleShaders++;
    }
    HRESULT hr = m_TexsPostScale.CheckCreate(m_pD3DDevEx, m_InternalTexFmt, m_windowRect.Width(), m_windowRect.Height(), numPostScaleShaders);
+   if (FAILED(hr)) {
+       m_bFinalPass = false;
+       m_bUseDither = false;
+       DLog(L"CDX9VideoProcessor::UpdatePostScaleTexures(): m_TexsPostScale.CheckCreate() failed with error {}", HR2Str(hr));
+   }
    //UpdateStatsPostProc();
}

But another problem was that video was rendered black (with working subs/osd). Due to pointer to surface being NULL.

I added some extra logging and checks, and managed to get the video working with these changes. But since the chroma handling is skipped, it is rendered in greyscale. Would it be possible to implement a proper fallback method for scaling without shaders? Similar to EVR-CP.

--- a/Source/DX9VideoProcessor.cpp
+++ b/Source/DX9VideoProcessor.cpp
@@ -2126,6 +2126,10 @@ HRESULT CDX9VideoProcessor::ConvertColorPass(IDirect3DSurface9* pRenderTarget)
    hr = m_pD3DDevEx->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);

    hr = m_pD3DDevEx->SetTexture(0, m_TexSrcVideo.pTexture);
+   if (FAILED(hr)) {
+       return hr;
+   }
+
    DWORD FVF = D3DFVF_TEX1;
    hr = m_pD3DDevEx->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
    hr = m_pD3DDevEx->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
@@ -2214,8 +2218,10 @@ HRESULT CDX9VideoProcessor::ResizeShaderPass(IDirect3DTexture9* pTexture, IDirec
            // use only float textures here
            hr = m_TexResize.Create(m_pD3DDevEx, D3DFMT_A16B16G16R16F,texWidth, texHeight, D3DUSAGE_RENDERTARGET);
            if (FAILED(hr)) {
-               DLog(L"CDX9VideoProcessor::ProcessTex() : m_TexResize.Create() failed with error {}", HR2Str(hr));
-               return TextureCopyRect(pTexture, srcRect, dstRect, D3DTEXF_LINEAR, m_iRotation, m_bFlip);
+               DLog(L"CDX9VideoProcessor::ResizeShaderPass : m_TexResize.Create() failed with error {}", HR2Str(hr));
+               hr = TextureCopyRect(pTexture, srcRect, dstRect, D3DTEXF_LINEAR, m_iRotation, m_bFlip);
+               DLogIf(FAILED(hr), L"CDX9VideoProcessor::ResizeShaderPass : TextureCopyRect() failed with error {}", HR2Str(hr));
+               return hr;
            }
        }

@@ -2331,12 +2337,13 @@ HRESULT CDX9VideoProcessor::Process(IDirect3DSurface9* pRenderTarget, const CRec
        pInputTexture = m_TexConvertOutput.pTexture;
        rSrc = rect;
    }
-   else if (m_PSConvColorData.bEnable) {
+   else if (m_PSConvColorData.bEnable && 0) { // FIXME: this solves black screen, but plays video in greyscale
        ConvertColorPass(m_TexConvertOutput.pSurface);
        pInputTexture = m_TexConvertOutput.pTexture;
        rSrc.SetRect(0, 0, m_TexConvertOutput.Width, m_TexConvertOutput.Height);
    }
-   else {
+
+   if (!pInputTexture) {
        pInputTexture = m_TexSrcVideo.pTexture;
    }

@@ -2444,11 +2451,11 @@ HRESULT CDX9VideoProcessor::TextureCopyRect(
    IDirect3DTexture9* pTexture, const CRect& srcRect, const CRect& dstRect,
    D3DTEXTUREFILTERTYPE filter, const int iRotation, const bool bFlip)
 {
-   HRESULT hr;
+   HRESULT hr = E_FAIL;

    D3DSURFACE_DESC desc;
-   if (!pTexture || FAILED(pTexture->GetLevelDesc(0, &desc))) {
-       return E_FAIL;
+   if (!pTexture || FAILED(hr = pTexture->GetLevelDesc(0, &desc))) {
+       return hr;
    }

    const float dx = 1.0f / desc.Width;
Aleksoid1978 commented 2 years ago

How i can get crash ? What settings and conditions ?

Aleksoid1978 commented 2 years ago

If shader scaling not working - use VP.

clsid2 commented 2 years ago

A fresh install of Windows 11 inside a VirtualBox virtual machine with VBoxSVGA graphics controller with 3D acceleration enabled. You can also use Window 10 to reproduce the black screen problem.

VP is also not working in this case.

The crash occurred with 10bit video plus dithering enabled. But black screen is also with 8bit video.

m_TexResize.Create() failed due to D3D error, TextureCopyRect() failed due to pTexture being NULL, and I tracked that down to ConvertColorPass() not working.

The patch above handles the failures and makes video play. But chroma is wrong due to the hacky workaround of skipping ConvertColorPass(). It would be good if this patch could be improved, so that we have three ways of scaling: VP/Shaders/Texture.

[1716] MpcVideoRenderer64.ax(tid a0c)        0 : CMpcVideoRenderer::CMpcVideoRenderer() 
[1716] MpcVideoRenderer64.ax(tid a0c)        0 : Windows 10 
[1716] MpcVideoRenderer64.ax(tid a0c)        0 : MPC Video Renderer 0.5.5.1766 (git-2021.09.22-701524f) x64 DEBUG 
[1716] MpcVideoRenderer64.ax(tid c4c)       15 : CDX9VideoProcessor::InitInternal() 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ReleaseDevice() 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ClearPostScaleShaders(). 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : Graphics D3D9 adapter: VirtualBox Graphics Adapter (WDDM) (80EE:BEEF) 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : Display Mode: 1280x1024, 60p 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : DeviceCaps:
[1716]   MaxTextureWidth                 : 16384
[1716]   MaxTextureHeight                : 16384
[1716]   PresentationInterval IMMEDIATE  : supported
[1716]   PresentationInterval ONE        : supported
[1716]   Caps READ_SCANLINE              : supported
[1716]   PixelShaderVersion              : 3.0
[1716]   MaxPixelShader30InstructionSlots: 4096 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ReleaseDevice() 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid c4c)       31 : CDX9VideoProcessor::ClearPostScaleShaders(). 
[1716] MpcVideoRenderer64.ax(tid c4c)      246 :     => CreateDeviceEx() : S_OK 
[1716] MpcVideoRenderer64.ax(tid a0c)      247 : Direct3D9 initialization successfully! 
[1716] MpcVideoRenderer64.ax(tid c4c)      249 : CDX9VideoProcessor::InitInternal() 
[1716] MpcVideoRenderer64.ax(tid c4c)      249 : Graphics D3D9 adapter: VirtualBox Graphics Adapter (WDDM) (80EE:BEEF) 
[1716] MpcVideoRenderer64.ax(tid c4c)      249 : Display Mode: 1280x1024, 60p 
[1716] MpcVideoRenderer64.ax(tid c4c)      249 : DeviceCaps:
[1716]   MaxTextureWidth                 : 16384
[1716]   MaxTextureHeight                : 16384
[1716]   PresentationInterval IMMEDIATE  : supported
[1716]   PresentationInterval ONE        : supported
[1716]   Caps READ_SCANLINE              : supported
[1716]   PixelShaderVersion              : 3.0
[1716]   MaxPixelShader30InstructionSlots: 4096 
[1716] MpcVideoRenderer64.ax(tid c4c)      250 :     => ResetEx() : S_OK 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CVideoRendererInputPin::ReceiveConnection() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CMpcVideoRenderer::SetMediaType()
[1716] MajorType : Video
[1716] SubType   : NV12
[1716] FormatType: VideoInfo2
[1716] BimapSize : 960 x 540
[1716] SourceRect: (0, 0, 960, 540)
[1716] SizeImage : 777600 bytes 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x288d2500 chroma:1 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x288d2500 chroma:1 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid a0c)      250 : CVideoRendererInputPin::GetAllocator() 
[1716] MpcVideoRenderer64.ax(tid aac)      420 : CDX9VideoProcessor::ClearPostScaleShaders(). 
[2072] Suspending
[1716] MpcVideoRenderer64.ax(tid aac)      592 : CMpcVideoRenderer::Pause() 
[1716] MpcVideoRenderer64.ax(tid f04)      602 : CMpcVideoRenderer::NewSegment() 
[1716] MpcVideoRenderer64.ax(tid 52c)      683 : CVideoRendererInputPin::ReceiveConnection() 
[1716] MpcVideoRenderer64.ax(tid 52c)      707 : CVideoRendererInputPin::GetAllocator() 
[1716] MpcVideoRenderer64.ax(tid 52c)      711 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid 52c)      735 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      742 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      744 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid 52c)      748 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      754 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      763 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x294d2581 chroma:1 
[1716] MpcVideoRenderer64.ax(tid 52c)      766 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid 52c)      771 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid 52c)      780 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid 52c)      790 : CMpcVideoRenderer::SetMediaType()
[1716] MajorType : Video
[1716] SubType   : NV12
[1716] FormatType: VideoInfo2
[1716] BimapSize : 960 x 540
[1716] SourceRect: (0, 0, 960, 540)
[1716] SizeImage : 777600 bytes 
[1716] MpcVideoRenderer64.ax(tid 52c)      790 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid 52c)      792 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      803 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      823 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid 52c)      824 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      824 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      824 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x294d2581 chroma:1 
[1716] MpcVideoRenderer64.ax(tid 52c)      824 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid 52c)      824 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid 52c)      827 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid 52c)      835 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid 52c)      835 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x294d2581 chroma:1 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid 52c)      836 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid 52c)      838 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid 52c)      839 : CMpcVideoRenderer::SetMediaType()
[1716] MajorType : Video
[1716] SubType   : NV12
[1716] FormatType: VideoInfo2
[1716] BimapSize : 960 x 540
[1716] SourceRect: (0, 0, 960, 540)
[1716] SizeImage : 777600 bytes 
[1716] MpcVideoRenderer64.ax(tid 52c)      839 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid 52c)      839 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x294d2581 chroma:1 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid 52c)      841 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid 52c)      844 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid 52c)      844 : CDX9VideoProcessor::InitMediaType() 
[1716] MpcVideoRenderer64.ax(tid 52c)      845 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      845 : CDX9VideoProcessor::InitializeDXVA2VP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : CDXVA2VP::InitVideoProcessor() : Create test input surface failed with error D3DERR_INVALIDCALL 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : CDX9VideoProcessor::ReleaseVP() 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : CDX9VideoProcessor::InitializeTexVP() started with input surface: NV12, 960 x 540 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : GetShaderConvertColor() started for NV12 960x540 extfmt:0x294d2581 chroma:1 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : GetShaderConvertColor() frame consists of 2 planes 
[1716] MpcVideoRenderer64.ax(tid 52c)      847 : GetShaderConvertColor() set chroma location MPEG-2 
[1716] MpcVideoRenderer64.ax(tid 52c)      849 : CDX9VideoProcessor::InitializeTexVP() completed successfully 
[1716] MpcVideoRenderer64.ax(tid a6c)      900 : CMpcVideoRenderer::Run() 
Aleksoid1978 commented 2 years ago

No need use VR in VirtualBox :) MPC VR can use VR or Shaders.

v0lt commented 2 years ago

What is your version of VirtualBox? What is your version of your guest Windows 10? Windows 11 is now very problemful and I will not spend time on this system. Is supported 3D installed and how many video memory allocated?

I also confirm that we do not support MPC VR in virtual machines.

clsid2 commented 2 years ago

Latest version of VirtualBox. Yes, with 3D enabled and 256MB gpu ram (max). Windows 10 2004, but any other recent version should be the same.

There have been people with black screen issues on normal systems as well. So that might be because of same problem. It would be good if the VR could work with basic functionality even when shaders fail. I think it should be possible with some small changes. I already partially works with the few changes in my patch above.

It seems to be the texture allocation functions that fail. Possibly due to the small amount of GPU ram.

Aleksoid1978 commented 2 years ago

In current implementation impossible using when VR and Shaders fail. How do color conversion ?

P.S. If it's very-very bad/old system - don't need use MPC VR, that's all.

clsid2 commented 2 years ago

Another thing: InitMediaType() is called several times. I think it would be good idea to check if is same as current medatype, and then skip doing a re-init.

v0lt commented 2 years ago

Another thing: InitMediaType() is called several times. I think it would be good idea to check if is same as current medatype, and then skip doing a re-init.

There are several reasons why this happens. Reducing some initializations is very difficult to implement.