D3D9: Support old-style user clip planes.

This fixes negative Z issues on D3D9 in many cases, such as #14168
and #16574, but only when clip planes are supported.
This commit is contained in:
Unknown W. Brackets 2022-12-18 11:01:05 -08:00
parent 710e63814f
commit 3e77cb1475
5 changed files with 20 additions and 0 deletions

View file

@ -361,6 +361,7 @@ public:
DxState1<D3DRS_CULLMODE, D3DCULL_NONE> cullMode;
DxState1<D3DRS_SHADEMODE, D3DSHADE_GOURAUD> shadeMode;
DxState1<D3DRS_CLIPPLANEENABLE, 0> clipPlaneEnable;
BoolState<D3DRS_ZENABLE, false> depthTest;

View file

@ -177,6 +177,8 @@ public:
void Apply(LPDIRECT3DDEVICE9 device) {
dxstate.cullMode.set(cullMode);
dxstate.scissorTest.enable();
// Force user clipping off.
dxstate.clipPlaneEnable.set(0);
}
};
@ -766,6 +768,8 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
caps_.isTilingGPU = false;
caps_.multiSampleLevelsMask = 1; // More could be supported with some work.
caps_.clipPlanesSupported = caps.MaxUserClipPlanes;
if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) {
caps_.anisoSupported = true;
}

View file

@ -580,6 +580,9 @@ struct DeviceCaps {
// From the other backends, we can detect if D3D9 support is known bad (like on Xe) and disable it.
bool supportsD3D9;
// Old style, for older GL or Direct3D 9.
u32 clipPlanesSupported;
u32 multiSampleLevelsMask; // Bit n is set if (1 << n) is a valid multisample level. Bit 0 is always set.
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};

View file

@ -452,6 +452,12 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) {
float data[4] = { viewZScale, viewZCenter, reverseTranslate, reverseScale };
VSSetFloatUniform4(CONST_VS_DEPTHRANGE, data);
if (draw_->GetDeviceCaps().clipPlanesSupported >= 1) {
float clip[4] = { 0.0f, 0.0f, reverseScale, 1.0f - reverseTranslate * reverseScale };
// Well, not a uniform, but we treat it as one like other backends.
device_->SetClipPlane(0, clip);
}
}
if (dirtyUniforms & DIRTY_CULLRANGE) {
float minValues[4], maxValues[4];

View file

@ -201,6 +201,12 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
} else {
dxstate.shadeMode.set(gstate.getShadeMode() == GE_SHADE_GOURAUD ? D3DSHADE_GOURAUD : D3DSHADE_FLAT);
}
// We use fixed-function user clipping on D3D9, where available, for negative Z clipping.
if (draw_->GetDeviceCaps().clipPlanesSupported >= 1) {
bool wantClip = !gstate.isModeThrough();
dxstate.clipPlaneEnable.set(wantClip ? 1 : 0);
}
}
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {