diff --git a/src/core/hle/D3D8/XbD3D8Types.h b/src/core/hle/D3D8/XbD3D8Types.h index 42eced178..93ae10731 100644 --- a/src/core/hle/D3D8/XbD3D8Types.h +++ b/src/core/hle/D3D8/XbD3D8Types.h @@ -62,7 +62,6 @@ #define D3DXAssembleShader D3DXAssembleShader #define FullScreen_PresentationInterval PresentationInterval // a field in D3DPRESENT_PARAMETERS #define D3DLockData void -#define PixelShaderConstantType float #define D3DADAPTER_IDENTIFIER D3DADAPTER_IDENTIFIER9 #define D3DCAPS D3DCAPS9 diff --git a/src/core/hle/D3D8/XbPixelShader.cpp b/src/core/hle/D3D8/XbPixelShader.cpp index 63766d7ec..9d0af8b27 100644 --- a/src/core/hle/D3D8/XbPixelShader.cpp +++ b/src/core/hle/D3D8/XbPixelShader.cpp @@ -68,6 +68,8 @@ #include "Direct3D9\RenderStates.h" // For XboxRenderStateConverter +#include + extern XboxRenderStateConverter XboxRenderStates; // Declared in Direct3D9.cpp #define DbgPshPrintf \ @@ -801,7 +803,7 @@ enum typedef struct _PSH_RECOMPILED_SHADER { xbox::X_D3DPIXELSHADERDEF PSDef; std::string NewShaderStr; - DWORD ConvertedHandle; + IDirect3DPixelShader* ConvertedHandle; } PSH_RECOMPILED_SHADER, *PPSH_RECOMPILED_SHADER; @@ -5828,7 +5830,7 @@ static const hRet = g_pD3DDevice->CreatePixelShader ( pFunction, - (IDirect3DPixelShader**)(&(Result.ConvertedHandle)) //fixme + &Result.ConvertedHandle ); if (hRet != D3D_OK) { @@ -5852,7 +5854,7 @@ static const std::vector g_RecompiledPixelShaders; -bool ArePSDefsIdentical(xbox::X_D3DPIXELSHADERDEF &PSDef1, xbox::X_D3DPIXELSHADERDEF &PSDef2) +bool ArePSDefsIdentical(const xbox::X_D3DPIXELSHADERDEF &PSDef1, const xbox::X_D3DPIXELSHADERDEF &PSDef2) { // Only compare the [*]-marked members, which forms the unique shader declaration (ignore the constants and Xbox Direct3D8 run-time fields) : // [*] DWORD PSAlphaInputs[8]; // X_D3DRS_PSALPHAINPUTS0..X_D3DRS_PSALPHAINPUTS7 : Alpha inputs for each stage @@ -5887,16 +5889,6 @@ bool ArePSDefsIdentical(xbox::X_D3DPIXELSHADERDEF &PSDef1, xbox::X_D3DPIXELSHADE void DxbxUpdateActivePixelShader() // NOPATCH { - xbox::X_D3DPIXELSHADERDEF *pPSDef; - PPSH_RECOMPILED_SHADER RecompiledPixelShader; - DWORD ConvertedPixelShaderHandle; - DWORD CurrentPixelShader; - int i; - D3DCOLOR dwColor; - D3DXCOLOR fColor[PSH_XBOX_CONSTANT_MAX]; - - HRESULT Result = D3D_OK; - // The first RenderState is PSAlpha, // The pixel shader is stored in pDevice->m_pPixelShader // For now, we still patch SetPixelShader and read from there... @@ -5909,7 +5901,7 @@ void DxbxUpdateActivePixelShader() // NOPATCH // manually read from D3D__RenderState[X_D3DRS_PSTEXTUREMODES] for that one field. // See D3DDevice_SetPixelShaderCommon which implements this - pPSDef = g_pXbox_PixelShader != nullptr ? (xbox::X_D3DPIXELSHADERDEF*)(XboxRenderStates.GetPixelShaderRenderStatePointer()) : nullptr; + const xbox::X_D3DPIXELSHADERDEF *pPSDef = g_pXbox_PixelShader != nullptr ? (xbox::X_D3DPIXELSHADERDEF*)(XboxRenderStates.GetPixelShaderRenderStatePointer()) : nullptr; if (pPSDef != nullptr) { @@ -5918,13 +5910,13 @@ void DxbxUpdateActivePixelShader() // NOPATCH // Copy-in the PSTextureModes value which is stored outside the range of Xbox pixel shader render state slots : PSDefCopy.PSTextureModes = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSTEXTUREMODES); - RecompiledPixelShader = nullptr; + const PSH_RECOMPILED_SHADER* RecompiledPixelShader = nullptr; // Now, see if we already have a shader compiled for this declaration : // TODO : Change g_RecompiledPixelShaders into an unordered_map, hash just the identifying PSDef members, and add cache eviction (clearing host resources when pruning) - for (auto it = g_RecompiledPixelShaders.begin(); it != g_RecompiledPixelShaders.end(); ++it) { - if (ArePSDefsIdentical(it->PSDef, PSDefCopy)) { - RecompiledPixelShader = &(*it); + for (const auto& it : g_RecompiledPixelShaders) { + if (ArePSDefsIdentical(it.PSDef, PSDefCopy)) { + RecompiledPixelShader = ⁢ break; } } @@ -5937,11 +5929,12 @@ void DxbxUpdateActivePixelShader() // NOPATCH // Switch to the converted pixel shader (if it's any different from our currently active // pixel shader, to avoid many unnecessary state changes on the local side). - ConvertedPixelShaderHandle = RecompiledPixelShader->ConvertedHandle; + IDirect3DPixelShader* ConvertedPixelShaderHandle = RecompiledPixelShader->ConvertedHandle; - g_pD3DDevice->GetPixelShader(/*out*/(IDirect3DPixelShader**)(&CurrentPixelShader)); - if (CurrentPixelShader != ConvertedPixelShaderHandle) - g_pD3DDevice->SetPixelShader((IDirect3DPixelShader*)ConvertedPixelShaderHandle); + Microsoft::WRL::ComPtr CurrentPixelShader; + g_pD3DDevice->GetPixelShader(/*out*/CurrentPixelShader.GetAddressOf()); + if (CurrentPixelShader.Get() != ConvertedPixelShaderHandle) + g_pD3DDevice->SetPixelShader(ConvertedPixelShaderHandle); // TODO: Figure out a method to forward the vertex-shader oFog output to the pixel shader FOG input register : // We could use the unused oT4.x to output fog from the vertex shader, and read it with 'texcoord t4' in pixel shader! @@ -5974,67 +5967,65 @@ void DxbxUpdateActivePixelShader() // NOPATCH // Set constants, not based on g_PixelShaderConstants, but based on // the render state slots containing the pixel shader constants, // as these could have been updated via SetRenderState or otherwise : - for (i = 0; i < PSH_XBOX_CONSTANT_MAX; i++) - { + D3DXCOLOR fColor[PSH_XBOX_CONSTANT_MAX]; + for (int i = 0; i < PSH_XBOX_CONSTANT_MAX; i++) + { // Assume all constants are in use (this is much easier than tracking them for no other purpose than to skip a few here) - { - // Read the color from the corresponding render state slot : - switch (i) { - case PSH_XBOX_CONSTANT_FOG: - // Note : FOG.RGB is correct like this, but FOG.a should be coming - // from the vertex shader (oFog) - however, D3D8 does not forward this... - fColor[i] = dwColor = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_FOGCOLOR); - break; - case PSH_XBOX_CONSTANT_FC0: - fColor[i] = dwColor = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSFINALCOMBINERCONSTANT0); - break; - case PSH_XBOX_CONSTANT_FC1: - fColor[i] = dwColor = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSFINALCOMBINERCONSTANT1); - break; - case PSH_XBOX_CONSTANT_BEM + 0: - case PSH_XBOX_CONSTANT_BEM + 1: - case PSH_XBOX_CONSTANT_BEM + 2: - case PSH_XBOX_CONSTANT_BEM + 3: - { - int stage = i - PSH_XBOX_CONSTANT_BEM; - DWORD* value = (DWORD*)&fColor[i]; + // Read the color from the corresponding render state slot : + switch (i) { + case PSH_XBOX_CONSTANT_FOG: + // Note : FOG.RGB is correct like this, but FOG.a should be coming + // from the vertex shader (oFog) - however, D3D8 does not forward this... + fColor[i] = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_FOGCOLOR); + break; + case PSH_XBOX_CONSTANT_FC0: + fColor[i] = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSFINALCOMBINERCONSTANT0); + break; + case PSH_XBOX_CONSTANT_FC1: + fColor[i] = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSFINALCOMBINERCONSTANT1); + break; + case PSH_XBOX_CONSTANT_BEM + 0: + case PSH_XBOX_CONSTANT_BEM + 1: + case PSH_XBOX_CONSTANT_BEM + 2: + case PSH_XBOX_CONSTANT_BEM + 3: + { + int stage = i - PSH_XBOX_CONSTANT_BEM; + DWORD* value = (DWORD*)&fColor[i]; - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT00, &value[0]); - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT01, &value[1]); - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT11, &value[2]); - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT10, &value[3]); - break; - } - case PSH_XBOX_CONSTANT_LUM + 0: - case PSH_XBOX_CONSTANT_LUM + 1: - case PSH_XBOX_CONSTANT_LUM + 2: - case PSH_XBOX_CONSTANT_LUM + 3: - { - int stage = i - PSH_XBOX_CONSTANT_LUM; - DWORD* value = (DWORD*)&fColor[i]; - - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVLSCALE, &value[0]); - g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVLOFFSET, &value[1]); - value[2] = 0; - value[3] = 0; - break; - } - default: // PSH_XBOX_CONSTANT_C0..C15 are stored as-is in (and should thus be read from) the Xbox render state pixel shader constant slots - fColor[i] = dwColor = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSCONSTANT0_0 + i - PSH_XBOX_CONSTANT_C0); - break; + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT00, &value[0]); + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT01, &value[1]); + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT11, &value[2]); + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVMAT10, &value[3]); + break; } - } + case PSH_XBOX_CONSTANT_LUM + 0: + case PSH_XBOX_CONSTANT_LUM + 1: + case PSH_XBOX_CONSTANT_LUM + 2: + case PSH_XBOX_CONSTANT_LUM + 3: + { + int stage = i - PSH_XBOX_CONSTANT_LUM; + DWORD* value = (DWORD*)&fColor[i]; - // Set all host constant values using a single call: - g_pD3DDevice->SetPixelShaderConstantF(0, (PixelShaderConstantType*)(&fColor[0]), PSH_XBOX_CONSTANT_MAX); - // Note PSH_XBOX_CONSTANT_MUL0 and PSH_XBOX_CONSTANT_MUL1 fall outside PSH_XBOX_CONSTANT_MAX - // and have already been 'PO_DEF'ined at the start of ConvertConstantsToNative + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVLSCALE, &value[0]); + g_pD3DDevice->GetTextureStageState(stage, D3DTSS_BUMPENVLOFFSET, &value[1]); + value[2] = 0; + value[3] = 0; + break; + } + default: // PSH_XBOX_CONSTANT_C0..C15 are stored as-is in (and should thus be read from) the Xbox render state pixel shader constant slots + fColor[i] = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_PSCONSTANT0_0 + i - PSH_XBOX_CONSTANT_C0); + break; + } } + + // Set all host constant values using a single call: + g_pD3DDevice->SetPixelShaderConstantF(0, reinterpret_cast(fColor), PSH_XBOX_CONSTANT_MAX); + // Note PSH_XBOX_CONSTANT_MUL0 and PSH_XBOX_CONSTANT_MUL1 fall outside PSH_XBOX_CONSTANT_MAX + // and have already been 'PO_DEF'ined at the start of ConvertConstantsToNative } else { - ConvertedPixelShaderHandle = 0; - g_pD3DDevice->SetPixelShader((IDirect3DPixelShader*)ConvertedPixelShaderHandle); + g_pD3DDevice->SetPixelShader(nullptr); } }