1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-23 10:54:14 +01:00

[d3d8] Add shadow perspective divide hack for Splinter Cell

This commit is contained in:
Jeff 2025-01-31 19:01:02 +00:00 committed by Philip Rebohle
parent f2802dd2ff
commit 0aebedae16
4 changed files with 43 additions and 4 deletions

View File

@ -1368,6 +1368,27 @@ namespace dxvk {
D3D8Texture2D* tex = static_cast<D3D8Texture2D*>(pTexture);
// Splinter Cell: Force perspective divide when a shadow map is bound to slot 0
if (unlikely(m_d3d8Options.shadowPerspectiveDivide && Stage == 0)) {
if (tex) {
D3DSURFACE_DESC surf;
tex->GetLevelDesc(0, &surf);
if (isDepthStencilFormat(surf.Format)) {
// If we bound a depth texture to stage 0 then we need to set the projected flag for stage 0 and 1
// Stage 1 is a non-depth light cookie texture but still requires perspective divide to work
GetD3D9()->SetTextureStageState(0, d3d9::D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED);
GetD3D9()->SetTextureStageState(1, d3d9::D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED);
m_shadowPerspectiveDivide = true;
} else if (m_shadowPerspectiveDivide) {
// Non-depth texture bound. Game will reset the transform flags to 0 on its own
m_shadowPerspectiveDivide = false;
}
} else if (m_shadowPerspectiveDivide) {
// Texture unbound. Game will reset the transform flags to 0 on its own
m_shadowPerspectiveDivide = false;
}
}
if (unlikely(m_textures[Stage] == tex))
return D3D_OK;
@ -1401,6 +1422,13 @@ namespace dxvk {
DWORD Value) {
d3d9::D3DSAMPLERSTATETYPE stateType = GetSamplerStateType9(Type);
if (unlikely(m_d3d8Options.shadowPerspectiveDivide && Type == D3DTSS_TEXTURETRANSFORMFLAGS)) {
// Splinter Cell: Ignore requests to change texture transform flags
// to 0 while shadow mapping perspective divide mode is enabled
if (m_shadowPerspectiveDivide && (Stage == 0 || Stage == 1))
return D3D_OK;
}
StateChange();
if (stateType != -1u) {
// if the type has been remapped to a sampler state type:

View File

@ -393,6 +393,8 @@ namespace dxvk {
m_backBuffers.resize(m_presentParams.BackBufferCount);
m_autoDepthStencil = nullptr;
m_shadowPerspectiveDivide = false;
}
inline void RecreateBackBuffersAndAutoDepthStencil() {
@ -434,6 +436,8 @@ namespace dxvk {
// Controls fixed-function exclusive mode (no PS support)
bool m_isFixedFunctionOnly = false;
bool m_shadowPerspectiveDivide = false;
D3D8StateBlock* m_recorder = nullptr;
DWORD m_recorderToken = 0;
DWORD m_token = 0;

View File

@ -42,13 +42,19 @@ namespace dxvk {
/// it was brought in line with standard D3D9 behavior.
bool forceLegacyDiscard = false;
/// Splinter Cell expects shadow map texture coordinates to be perspective divided
/// even though D3DTTFF_PROJECTED is never set for any texture coordinates. This flag
/// forces that flag for the necessary stages when a depth texture is bound to slot 0
bool shadowPerspectiveDivide = false;
D3D8Options() {}
D3D8Options(const Config& config) {
auto forceVsDeclStr = config.getOption<std::string>("d3d8.forceVsDecl", "");
batching = config.getOption<bool> ("d3d8.batching", batching);
placeP8InScratch = config.getOption<bool> ("d3d8.placeP8InScratch", placeP8InScratch);
forceLegacyDiscard = config.getOption<bool> ("d3d8.forceLegacyDiscard", forceLegacyDiscard);
auto forceVsDeclStr = config.getOption<std::string>("d3d8.forceVsDecl", "");
batching = config.getOption<bool> ("d3d8.batching", batching);
placeP8InScratch = config.getOption<bool> ("d3d8.placeP8InScratch", placeP8InScratch);
forceLegacyDiscard = config.getOption<bool> ("d3d8.forceLegacyDiscard", forceLegacyDiscard);
shadowPerspectiveDivide = config.getOption<bool> ("d3d8.shadowPerspectiveDivide", shadowPerspectiveDivide);
parseVsDecl(forceVsDeclStr);
}

View File

@ -1199,6 +1199,7 @@ namespace dxvk {
* Fixes shadow buffers and alt-tab */
{ R"(\\splintercell\.exe$)", {{
{ "d3d8.scaleDref", "24" },
{ "d3d8.shadowPerspectiveDivide", "True" },
{ "d3d9.deviceLossOnFocusLoss", "True" },
}} },
/* Trainz v1.3 (2001) *