[d3d9] Implement capturing lights in state blocks

This commit is contained in:
Robin Kertels 2022-11-21 00:37:39 +01:00 committed by Joshie
parent 1a3b576d35
commit 4796eb0b0d
3 changed files with 72 additions and 2 deletions

View File

@ -1728,7 +1728,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
if (unlikely(ShouldRecord())) {
Logger::warn("D3D9DeviceEx::SetLight: State block not implemented.");
m_recorder->SetLight(Index, pLight);
return D3D_OK;
}
@ -1762,6 +1762,11 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::LightEnable(DWORD Index, BOOL Enable) {
D3D9DeviceLock lock = LockDevice();
if (unlikely(ShouldRecord())) {
m_recorder->LightEnable(Index, Enable);
return D3D_OK;
}
if (unlikely(Index >= m_state.lights.size()))
m_state.lights.resize(Index + 1);

View File

@ -157,6 +157,46 @@ namespace dxvk {
}
HRESULT D3D9StateBlock::SetLight(DWORD Index, const D3DLIGHT9* pLight) {
if (Index >= m_state.lights.size())
m_state.lights.resize(Index + 1);
m_state.lights[Index] = *pLight;
m_captures.flags.set(D3D9CapturedStateFlag::Lights);
return D3D_OK;
}
HRESULT D3D9StateBlock::LightEnable(DWORD Index, BOOL Enable) {
if (unlikely(Index >= m_state.lights.size()))
m_state.lights.resize(Index + 1);
if (unlikely(!m_state.lights[Index]))
m_state.lights[Index] = DefaultLight;
if (m_state.IsLightEnabled(Index) == !!Enable)
return D3D_OK;
uint32_t searchIndex = UINT32_MAX;
uint32_t setIndex = Index;
if (!Enable)
std::swap(searchIndex, setIndex);
for (auto& idx : m_state.enabledLightIndices) {
if (idx == searchIndex) {
idx = setIndex;
break;
}
}
m_captures.lightEnabledChanges.set(Index, true);
m_captures.flags.set(D3D9CapturedStateFlag::Lights);
return D3D_OK;
}
HRESULT D3D9StateBlock::SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix) {
m_state.transforms[idx] = ConvertMatrix(pMatrix);
@ -495,6 +535,8 @@ namespace dxvk {
m_captures.flags.set(D3D9CapturedStateFlag::VertexDecl);
m_captures.flags.set(D3D9CapturedStateFlag::StreamFreq);
m_captures.flags.set(D3D9CapturedStateFlag::Lights);
m_captures.lightEnabledChanges.setN(m_deviceState->lights.size());
for (uint32_t i = 0; i < caps::MaxStreams; i++)
m_captures.streamFreq.set(i, true);

View File

@ -25,7 +25,8 @@ namespace dxvk {
StreamFreq,
Transforms,
TextureStages,
Material
Material,
Lights
};
using D3D9CapturedStateFlags = Flags<D3D9CapturedStateFlag>;
@ -61,6 +62,8 @@ namespace dxvk {
bit::bitset<caps::MaxOtherConstants> iConsts;
bit::bitset<caps::MaxOtherConstants> bConsts;
} psConsts;
bit::bitvector lightEnabledChanges;
};
enum class D3D9StateBlockType :uint32_t {
@ -120,6 +123,10 @@ namespace dxvk {
HRESULT SetMaterial(const D3DMATERIAL9* pMaterial);
HRESULT SetLight(DWORD Index, const D3DLIGHT9* pLight);
HRESULT LightEnable(DWORD Index, BOOL Enable);
HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix);
HRESULT SetStateTextureStageState(
@ -297,6 +304,22 @@ namespace dxvk {
dst->SetPixelBoolBitfield(i, m_captures.psConsts.bConsts.dword(i), src->psConsts.bConsts[i]);
}
}
if (m_captures.flags.test(D3D9CapturedStateFlag::Lights)) {
for (uint32_t i = 0; i < m_state.lights.size(); i++) {
if (!m_state.lights[i].has_value())
continue;
dst->SetLight(i, &m_state.lights[i].value());
}
for (uint32_t i = 0; i < m_captures.lightEnabledChanges.dwordCount(); i++) {
for (uint32_t consts : bit::BitMask(m_captures.lightEnabledChanges.dword(i))) {
uint32_t idx = i * 32 + consts;
dst->LightEnable(idx, m_state.IsLightEnabled(idx));
}
}
}
}
template <D3D9StateFunction Func>