@@ -96,7 +96,24 @@ namespace dxvk {
9696 }
9797
9898 void LightManager::clear () {
99+ if (!m_lightDebugUILock.owns_lock ()) {
100+ m_lightDebugUILock.lock ();
101+ }
99102 m_lights.clear ();
103+ m_linearizedLights.clear ();
104+ m_lightDebugUILock.unlock ();
105+ }
106+
107+ void LightManager::clearFromUIThread () {
108+ // This needs to wait for `m_lightDebugUILock` to be unlocked, so it doesn't
109+ // cause crashes.
110+ std::lock_guard<std::mutex> lock (m_lightUIMutex);
111+ m_lights.clear ();
112+ m_linearizedLights.clear ();
113+
114+ // Note: Fallback light reset here so that changes to its settings will take effect, does not need to be part
115+ // of usual light clearing logic though.
116+ m_fallbackLight.reset ();
100117 }
101118
102119 void LightManager::garbageCollectionInternal () {
@@ -126,6 +143,9 @@ namespace dxvk {
126143 }
127144
128145 void LightManager::garbageCollection (RtCamera& camera) {
146+ if (!m_lightDebugUILock.owns_lock ()) {
147+ m_lightDebugUILock.lock ();
148+ }
129149 if (RtxOptions::AntiCulling::isLightAntiCullingEnabled ()) {
130150 cFrustum& cameraLightAntiCullingFrustum = camera.getLightAntiCullingFrustum ();
131151 for (auto & [lightHash, rtLight] : getLightTable ()) {
@@ -162,6 +182,7 @@ namespace dxvk {
162182 }
163183
164184 garbageCollectionInternal ();
185+ m_lightDebugUILock.unlock ();
165186 }
166187
167188 void LightManager::dynamicLightMatching () {
@@ -316,7 +337,7 @@ namespace dxvk {
316337 // can be processed like all other lights without complex logic at the cost of potentially more computational
317338 // cost, but it might actually work out in favor of performance since unordered map traversal done redundantly
318339 // may be more expensive than simple vector traversal on the linearized list.
319-
340+
320341 m_linearizedLights.clear ();
321342
322343 if (m_fallbackLight) {
@@ -333,7 +354,7 @@ namespace dxvk {
333354 auto found = m_externalLights.find (handle);
334355 if (found != m_externalLights.end ()) {
335356 m_linearizedLights.emplace_back (&found->second );
336- }
357+ }
337358 }
338359
339360 // Count the active light of each type
@@ -569,6 +590,11 @@ namespace dxvk {
569590 }
570591
571592 RtLight* LightManager::addLight (const RtLight& rtLight, const RtLightAntiCullingType antiCullingType, const XXH64_hash_t lightToReplace) {
593+ if (!m_lightDebugUILock.owns_lock ()) {
594+ // As addLight can actually erase old lights, we need to lock the mutex starting from the first call each frame.
595+ m_lightDebugUILock.lock ();
596+ }
597+
572598 // This light is "off". This includes negative valued lights which in D3D games originally would act as subtractive lighting.
573599 const Vector3 originalRadiance = rtLight.getRadiance ();
574600 if (originalRadiance.x < 0 || originalRadiance.y < 0 || originalRadiance.z < 0
0 commit comments