Remove ConcurrentSystemLocker and use ReadWriteLock instead of better threading synchronization

This commit is contained in:
Wojtek Figat
2025-09-04 14:48:52 +02:00
parent c44d939c08
commit 3e363c8275
16 changed files with 107 additions and 194 deletions

View File

@@ -106,7 +106,7 @@ namespace
Asset::LoadResult ParticleEmitter::load()
{
PROFILE_MEM(Particles);
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
// Load the graph
const auto surfaceChunk = GetChunk(SHADER_FILE_CHUNK_VISJECT_SURFACE);
@@ -330,6 +330,7 @@ Asset::LoadResult ParticleEmitter::load()
// Wait for resources used by the emitter to be loaded
// eg. texture used to place particles on spawn needs to be available
// Free Particles::SystemLocker when waiting on asset load to prevent lock-contention.
bool waitForAsset = false;
for (const auto& node : Graph.Nodes)
{
@@ -341,7 +342,7 @@ Asset::LoadResult ParticleEmitter::load()
if (!waitForAsset)
{
waitForAsset = true;
Particles::SystemLocker.End(true);
Particles::SystemLocker.WriteUnlock();
}
WaitForAsset(texture);
}
@@ -354,20 +355,20 @@ Asset::LoadResult ParticleEmitter::load()
if (!waitForAsset)
{
waitForAsset = true;
Particles::SystemLocker.End(true);
Particles::SystemLocker.WriteUnlock();
}
WaitForAsset((Asset*)parameter.Value);
}
}
if (waitForAsset)
Particles::SystemLocker.Begin(true);
Particles::SystemLocker.WriteLock();
return LoadResult::Ok;
}
void ParticleEmitter::unload(bool isReloading)
{
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
#if COMPILE_WITH_SHADER_COMPILER
UnregisterForShaderReloads(this);
#endif
@@ -458,7 +459,7 @@ bool ParticleEmitter::SaveSurface(const BytesContainer& data)
{
if (OnCheckSave())
return true;
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
ScopeLock lock(Locker);
// Release all chunks

View File

@@ -43,7 +43,7 @@ ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, cons
Asset::LoadResult ParticleEmitterFunction::load()
{
PROFILE_MEM(Particles);
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
// Load graph
const auto surfaceChunk = GetChunk(0);
@@ -96,7 +96,7 @@ Asset::LoadResult ParticleEmitterFunction::load()
void ParticleEmitterFunction::unload(bool isReloading)
{
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
Graph.Clear();
#if COMPILE_WITH_PARTICLE_GPU_GRAPH
GraphGPU.Clear();
@@ -189,7 +189,7 @@ bool ParticleEmitterFunction::SaveSurface(const BytesContainer& data) const
{
if (OnCheckSave())
return true;
ConcurrentSystemLocker::WriteScope systemScope(Particles::SystemLocker);
ScopeWriteLock systemScope(Particles::SystemLocker);
ScopeLock lock(Locker);
// Set Visject Surface data

View File

@@ -134,7 +134,7 @@ namespace ParticleManagerImpl
using namespace ParticleManagerImpl;
TaskGraphSystem* Particles::System = nullptr;
ConcurrentSystemLocker Particles::SystemLocker;
ReadWriteLock Particles::SystemLocker;
bool Particles::EnableParticleBufferPooling = true;
float Particles::ParticleBufferRecycleTimeout = 10.0f;
@@ -680,7 +680,7 @@ void CleanupGPUParticlesSorting()
void DrawEmittersGPU(RenderContextBatch& renderContextBatch)
{
PROFILE_GPU_CPU_NAMED("DrawEmittersGPU");
ConcurrentSystemLocker::ReadScope systemScope(Particles::SystemLocker);
ScopeReadLock systemScope(Particles::SystemLocker);
GPUContext* context = GPUDevice::Instance->GetMainContext();
// Count draws and sorting passes needed for resources allocation
@@ -1135,7 +1135,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
viewsDrawModes &= effect->DrawModes;
// Setup
ConcurrentSystemLocker::ReadScope systemScope(SystemLocker);
ScopeReadLock systemScope(SystemLocker);
Matrix worlds[2];
Matrix::Translation(-viewOrigin, worlds[0]); // World
renderContextBatch.GetMainContext().View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
@@ -1277,7 +1277,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
void Particles::DebugDraw(ParticleEffect* effect)
{
PROFILE_CPU_NAMED("Particles.DrawDebug");
ConcurrentSystemLocker::ReadScope systemScope(SystemLocker);
ScopeReadLock systemScope(SystemLocker);
// Draw all emitters
for (auto& emitterData : effect->Instance.Emitters)
@@ -1304,7 +1304,7 @@ void UpdateGPU(RenderTask* task, GPUContext* context)
PROFILE_CPU_NAMED("GPUParticles");
PROFILE_GPU("GPU Particles");
PROFILE_MEM(Particles);
ConcurrentSystemLocker::ReadScope systemScope(Particles::SystemLocker);
ScopeReadLock systemScope(Particles::SystemLocker);
// Collect valid emitter tracks to update
struct GPUSim
@@ -1728,7 +1728,7 @@ void ParticlesSystem::Execute(TaskGraph* graph)
Active = true;
// Ensure no particle assets can be reloaded/modified during async update
Particles::SystemLocker.Begin(false);
Particles::SystemLocker.ReadLock();
// Setup data for async update
const auto& tickData = Time::Update;
@@ -1751,7 +1751,7 @@ void ParticlesSystem::PostExecute(TaskGraph* graph)
PROFILE_MEM(Particles);
// Cleanup
Particles::SystemLocker.End(false);
Particles::SystemLocker.ReadUnlock();
Active = false;
UpdateList.Clear();

View File

@@ -3,7 +3,6 @@
#pragma once
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Threading/ConcurrentSystemLocker.h"
class TaskGraphSystem;
struct RenderContextBatch;
@@ -28,8 +27,8 @@ API_CLASS(Static) class FLAXENGINE_API Particles
/// </summary>
API_FIELD(ReadOnly) static TaskGraphSystem* System;
// Data access locker for animations data.
static ConcurrentSystemLocker SystemLocker;
// Data access locker for particles data.
static ReadWriteLock SystemLocker;
public:
/// <summary>