From 1c6fc7b5b8192f66003a9a3d2d75d81bc88846be Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Thu, 2 Mar 2023 02:06:02 +0100 Subject: [PATCH] [d3d9] Clamp stage and type in [G,S]etTextureStageState This is what happens on the Nvidia D3D9 driver. Dawn of Magic 2 calls SetTextureStageState with a stage > 7 and expects that to succeed. --- src/d3d9/d3d9_device.cpp | 21 ++++++++------------- src/d3d9/d3d9_stateblock.cpp | 3 +++ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 0cf65cf0..f606c8db 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -2304,13 +2304,8 @@ namespace dxvk { if (unlikely(pValue == nullptr)) return D3DERR_INVALIDCALL; - *pValue = 0; - - if (unlikely(Stage >= caps::TextureStageCount)) - return D3DERR_INVALIDCALL; - - if (unlikely(dxvkType >= TextureStageStateCount)) - return D3DERR_INVALIDCALL; + Stage = std::min(Stage, DWORD(caps::TextureStageCount - 1)); + dxvkType = std::min(dxvkType, D3D9TextureStageStateTypes(DXVK_TSS_COUNT - 1)); *pValue = m_state.textureStages[Stage][dxvkType]; @@ -3876,14 +3871,14 @@ namespace dxvk { DWORD Stage, D3D9TextureStageStateTypes Type, DWORD Value) { + + // Clamp values instead of checking and returning INVALID_CALL + // Matches tests + Dawn of Magic 2 relies on it. + Stage = std::min(Stage, DWORD(caps::TextureStageCount - 1)); + Type = std::min(Type, D3D9TextureStageStateTypes(DXVK_TSS_COUNT - 1)); + D3D9DeviceLock lock = LockDevice(); - if (unlikely(Stage >= caps::TextureStageCount)) - return D3DERR_INVALIDCALL; - - if (unlikely(Type >= TextureStageStateCount)) - return D3DERR_INVALIDCALL; - if (unlikely(ShouldRecord())) return m_recorder->SetStateTextureStageState(Stage, Type, Value); diff --git a/src/d3d9/d3d9_stateblock.cpp b/src/d3d9/d3d9_stateblock.cpp index 9c0abba1..76ab1d64 100644 --- a/src/d3d9/d3d9_stateblock.cpp +++ b/src/d3d9/d3d9_stateblock.cpp @@ -213,6 +213,9 @@ namespace dxvk { DWORD Stage, D3D9TextureStageStateTypes Type, DWORD Value) { + Stage = std::min(Stage, DWORD(caps::TextureStageCount - 1)); + Type = std::min(Type, D3D9TextureStageStateTypes(DXVK_TSS_COUNT - 1)); + m_state.textureStages[Stage][Type] = Value; m_captures.flags.set(D3D9CapturedStateFlag::TextureStages);