Pcsx2: [Regression] D3D11 renderer adds black lines to bottom and right of the screen

Created on 8 Dec 2015  路  45Comments  路  Source: PCSX2/pcsx2

While I was taking screenshots for #1025 to showcase the bug, I noticed that the D3D11 renderer adds very thin black lines on the bottom and right side of the screen, cutting off a bit of the image. This did not happen in 1.2.1 and it does not happen in the D3D9 or OGL renderers.

6x

The lines are actually thicker in native resolution:
native.

Direct3D Low Priority Windows GS Regression Workaround Possible

Most helpful comment

Imo, this should stay open till it's fixed by default without any workaround.

All 45 comments

So you know the game...
Where did it broke?

Nvidia workaroud?

possibly? ugh... Can we just drop DX11? or ignore a thin black line.

@karasuhebi

could you try using Git bisect and find the commit which caused this issue ? @refractionpcsx2 is a bit busy lately, finding the commit will definitely save his time and make the fix a bit faster. :)

It probably is the nvidia workaround as I move the viewport over a little which seems to eleviate the stretching issue, but i am moving the top left to -0.001,-0.001 which would potentially make a black bar in the bottom and right edges.

that makes sense , I think the fix should be then some kind of proper handling for the view port changes. maybe when it only satisfies a certain condition the Top left co-ordinate could be changed ?

Thats the problem, it's a bug in the Nvidia drivers and we don't know exactly the situation that causes it. I did have a hack that made it always go through the geometry shader and that seemed to fix it for windows 7 and 8 but then it completely broke it in windows 10, which is frustrating.

Is still an issue? I didn't follow all hack iteration. (that being said, I see no reason to use D3D on Nvidia for most games).

A workaround is to use the gs window zoom function of the emulator. Settings zoom to something like 101% removes the outermost pixels. As it provides almost no negative side effects it can be constantly set to 101% independent on renderer choice.

Is still an issue? I didn't follow all hack iteration. (that being said, I see no reason to use D3D on Nvidia for most games).

Yes, it's still an issue. DX11 is still widely used, not just by AMD gamers, but also by gamers with a slightly less powerful system.

One question. Are the black lines an issue with all GPU drivers or only Nvidia?

I have the issue with a AMD GPU, so it can't be Nvidia only.

Ok thanks you. Initial issue was due to Nvidia driver but the hack impact everyone. Maybe one can add some code to check the GPU driver/adapter.

The black line is a result of the Nvidia hack, the stretching problem is only on Nvidia drivers.

Yeh it would be nice to check the driver/gpu vendor, as earlier Nvidia drivers were also fine.

what would be even nicer is to find the cause of the problem and fix it :P I know it's something to do with texture handling it doesn't like as I believe the stretching doesn't happen if the texture cache is disabled.

What needs to be changed in code to turn to hack off?

https://github.com/PCSX2/pcsx2/commit/60a90aa51c200b5998f172555e886570a657d117

You need to disable the changes to view port dimensions.

Did anyone test a recent Nvidia driver just to be sure the issue is still here.

No, the recent Nvidia drivers are a mess, I'm not installing them until they fix them properly. There is a hotfix out but apparently that introduces a bunch of other problems.

I don't have high hopes that they've even looked at addressing the problem.

I don't have high hopes that they've even looked at addressing the problem.

accidents are stil possible ;) Is there any way to report Dx error?

I saw

#ifdef DEBUG
    flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

but I think the good define is _DEBUG (there are a couple of DEBUG)

Could someone enable Depth Clip Plan on Dx. Set the following field to true.

    rd.DepthClipEnable = false; // ???

Edit: did some web search on google. As far as I understand it doesn't clip (remove) primitives outside of the zNear and zFar planes. The GL equivalent feature is a clamping of the Z value during the Z test (or before). So basically instead to cut primitive, you saturate them on zNear/zFar. I don't use this feature on GL and it doesn't exist in Dx9.

Could someone enable Depth Clip Plan on Dx. Set the following field to true.

What are you expecting that to do?

Is there any way to report Dx error?

Possibly, but I can't remember if you can actually see the problem happening or not. Due to its very random nature, capturing it and finding it in a debug log will be a complete nightmare. it could happen multiple times in 60 frames, it could happen once over 1000's of frames.

I really don't know the impact but a non standard rasterizer option is maybe not a good idea. Normally we don't need to disable clipping as z value ough to be between 0/1 already but it would be safer to clip it.

I dunno if it makes any sense, but I only see the stretching issue on Suikoden 4 (PAL) if I have "Large Framebuffer" disabled.

I seem to be able to trigger the issue at the language selector screen most of the time by just pausing and resuming, or by using the weave or bob interlacing modes and just waiting.

I'm using 4x native, NVIDIA 368.39.

It generally happens when there is a full screen 2d texture ( or video) , it would be interesting if it doesn't happen on the vp2 video with large frame buffer disabled

I think I may have duplicated this issue on R&C Going Commando. My desktop is using 4x native and running Nvidia Driver 373.06 (October 6th, 2016)

The animation is comparing DX9 HW and DX11 HW. It's really hard to see (I could still see it on my laptop screen) but DX11 has a razor thin black line on the right side of the screen in addition to the grey line on the bottom.

It's easier to see if you scroll to the bottom right.

@MrCK1 Yes, likely due to the viewport hack in dx11. See the -0.01 below.

        D3D11_VIEWPORT vp;
        memset(&vp, 0, sizeof(vp));

        vp.TopLeftX = (spritehack > 0 || isNative) ? 0.0f : -0.01f;
        vp.TopLeftY = (spritehack > 0 || isNative) ? 0.0f : -0.01f;
        vp.Width = (float)size.x;
        vp.Height = (float)size.y;
        vp.MinDepth = 0.0f;
        vp.MaxDepth = 1.0f;

        m_ctx->RSSetViewports(1, &vp);

@turtleli
Hum, it could be. I think there is a wrong setup (or UB) on scissor/viewport/clipping. Normally Vertex Shader output x,y,z,1.0 position. x and y must be clipped to [0 ; 1] range (UB otherwise). Then it is rasterized (projected or upscaled) on the view port so [vp.x ; vp.w] and [vp.y ; vp.h]. Then sceen position will be checked against the scissor.

Would it be possible to edit the 2 vertex shader to clamp x/y output between [-1 + epsilon ; 1 - epsilon] ? Ideally epsilon ough to be 0 but let take some margins to test if there is any impact.
Edit: and also try to enable z clipping (it must be enabled normally)

Note: if you can reproduce on a gs dump, I'm sure Nvidia will be happy to help.

I'll try making a gsdump of the video, see if it does it :P

For the record https://msdn.microsoft.com/fr-fr/library/windows/desktop/ff476198(v=vs.85).aspx

Enable clipping based on distance.

The hardware always performs x and y clipping of rasterized coordinates. When 
DepthClipEnable is set to the default鈥揟RUE, the hardware also clips the z value 
(that is, the hardware performs the last step of the following algorithm). 

            0 < w
           -w <= x <= w 
          -w <= y <= w 
            0 <= z <= w

When you set DepthClipEnable to FALSE, the hardware skips the z clipping 
(that is, the last step in the preceding algorithm). However, the hardware
 still performs the "0 < w" clipping. When z clipping is disabled, improper
 depth ordering at the pixel level might result. However, when z clipping
 is disabled, stencil shadow implementations are simplified. In other words,
 you can avoid complex special-case handling for geometry that goes beyond
 the back clipping plane. 

Not sure if that's relevant or not, it's not a clipping problem, the whole picture just stretches to double the size and moves half way down the screen :P

Disclaimer: This might be BS. ;)

It might be related to the StretchRect in GSTexture::CreateSource(), GSTextureCache.cpp, line 1402

if ((sRect == dRect).alltrue() && !shader)
{
    // code trimmed
}
else
{
    // Different size or not the same format
    sRect.z /= sTex->GetWidth();
    sRect.w /= sTex->GetHeight();

    if (half_right) {
        sRect.x = sRect.z/2.0f;
    }

    m_renderer->m_dev->StretchRect(sTex, sRect, dTex, dRect, shader, linear);
}

Suikoden 4 GS dump (actually xz compressed): suikostretch.gs.gz - I found it easier to cause stretching with bob interlacing.

For my Suikoden 4 test case: the image stretches 1.6x horizontally and doesn't stretch vertically.
At native the else case is never hit.
At 2x native, dRect has the values (0, 0, 800, 1024) and sRect has the values (0, 0 1280, 1024) when the if is evaluated, so the else branch is taken. 1280/800 = 1.6, 1024/1024 = 1, which matches the stretching ratio.

I used to have the fix on the stretchrect code, seemingly forcing it through the geometry shaders seemed to work for a while.

What happens if you force the stretch on native, even though it won't do much?

But beyond this, is this still our bug? or is it still an Nvidia driver bug? If this does work, can we reproduce it?

What happens if you force the stretch on native, even though it won't do much?

I don't observe any stretching.

But beyond this, is this still our bug? or is it still an Nvidia driver bug? If this does work, can we reproduce it?

I've no idea whose bug this is. I was just messing around since your earlier comment said there was vertical stretching in vp2, which isn't the case for Suikoden 4, so there had to be something in the GSdx code that has an influence on how the image stretches.

Well over time i've messed with stretchrect as I've suspected that also, but the viewport change also seemed to fix it, even though the offset should be really minor (it shouldn't even be visible really!) and that also seems to fix it, so I really don't know what variables are required to make it happen. At the moment it's more a case of covering your eyes, spin round, then point to something.

Do you always reproduce the issue with the dump ? Maybe dump the Dx/Gl call with a debug tool such as apitrace/visual studio. This logic of the texture cache is rather awful.

Texture are sampled relatively by the size. So 0.5 of a 1024 texture will sample texel 512. Due to upscaling your framebuffer is 1280x1024. However if you use 0.5 here you will sample 640, so the image is resized/cut to properly fit so 0.5 endup in 512.

Hum, I'm not sure it is legal to hava value above 1.0 in sRect. Behavior will depends on the clamp mode but it is a bit strange to overlap/clamp the texture.

It's reproducible, but the issue doesn't appear at any specific frame.

sRect seems to be {0, 0, 1, 1} when StretchRect is called from the GSTexture::CreateSource().

Yeah it happens randomly. Always specific scenarios, but the glitches occur at random events in that scenario

In this case, you can try to do a package for nvidia. With a link to the github source.

It would also be nice to try to output dx error/warning message. Potentially there is something uninitialized somewhere.

Is this still an ongoing issue ?

Maybe adding a hidden userhack can be a somewhat ok workaround.
Or
Vendor id detection in combination with the user hack so it's only active on nvidia and can be toggled.

Can I close this since the PR is merged @karasuhebi ?
There are 2 workarounds now.

  1. Adding "UserHacks_DisableNVhack=1 " in GSdx.ini
  2. Zooming the Window size to 100.50% or 101%

Imo, this should stay open till it's fixed by default without any workaround.

I second @ssakash.

If Nvidia would fix their drivers, we could remove the hack and then there would be no need for it. Unfortunately nobody knows how to replicate it to make a sample program and they refuse to touch emulators.

I'll reopen this since there is a similar issue with the amd point sampler workaround as well.

So there are still some issues left to iron out, luckily this one won't show up if "Allow 8bit textures" is disabled.

I will close this as the nvidia hack is applied only on nvidia gpus when upscaling only, and it can be toggled with Disable safe features option too.

There is also an amd hack but it isn't confirmed if that also causes a similar issue but at the opposite edges, that one on nvidia hardware can be avoided with keeping allow 8bit textures off. That's all we can do for now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jobs-git picture jobs-git  路  3Comments

RinMaru picture RinMaru  路  5Comments

GeekyGami picture GeekyGami  路  3Comments

Javed-Iqbal-1 picture Javed-Iqbal-1  路  5Comments

backgamon picture backgamon  路  5Comments