public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world) { Graphics = graphics; World = world; Options = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions; Resources = serviceProvider.GetRequiredService <ResourceManager>(); var stillAtlas = Resources.Atlas.GetStillAtlas(); var fogStart = 0; Shaders = new RenderingShaders(Graphics); Shaders.SetTextures(stillAtlas); Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0)); RenderDistance = Options.VideoOptions.RenderDistance; Options.VideoOptions.RenderDistance.Bind( (value, newValue) => { RenderDistance = newValue; }); Chunks = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>(); CancellationToken = new CancellationTokenSource(); BlockLightCalculations = new BlockLightCalculations((World)world); SkyLightCalculator = new SkyLightCalculations(); Func <ChunkCoordinates, ChunkCoordinates, int> orderingTool = (a, b) => { var pos = new ChunkCoordinates(World.Camera.Position); var aDistance = a.DistanceTo(pos); var bDistance = b.DistanceTo(pos); if (aDistance < bDistance) { return(-1); } if (bDistance > aDistance) { return(1); } return(0); }; UpdateQueue = new FancyQueue <ChunkCoordinates>(); UpdateBorderQueue = new FancyQueue <ChunkCoordinates>(); FastUpdateQueue = new FancyQueue <ChunkCoordinates>(); }
public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world) { Graphics = graphics; World = world; Options = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions; Resources = serviceProvider.GetRequiredService <ResourceManager>(); var stillAtlas = Resources.Atlas.GetStillAtlas(); var fogStart = 0; Shaders = new RenderingShaders(Graphics); Shaders.SetTextures(stillAtlas); Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0)); _renderSampler.MaxMipLevel = stillAtlas.LevelCount; RenderDistance = Options.VideoOptions.RenderDistance; Options.VideoOptions.RenderDistance.Bind( (value, newValue) => { RenderDistance = newValue; }); Chunks = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>(); CancellationToken = new CancellationTokenSource(); BlockLightCalculations = new BlockLightCalculations(world, CancellationToken.Token); SkyLightCalculator = new SkyLightCalculations(CancellationToken.Token); UpdateQueue = new FancyQueue <ChunkCoordinates>(); UpdateBorderQueue = new FancyQueue <ChunkCoordinates>(); FastUpdateQueue = new FancyQueue <ChunkCoordinates>(); }
private bool ProcessQueue() { if (Interlocked.Read(ref _threadsRunning) >= Options.VideoOptions.ChunkThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= queue.Count) { return(false); } Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (queue.TryDequeue(out var chunkCoordinates, cc => { return(IsWithinView(cc, World.Camera)); })) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } //SkyLightCalculator.TryProcess(chunkCoordinates); bool newChunk = chunk.IsNew; if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } chunk.UpdateBuffer(Graphics, World, chunkCoordinates.DistanceTo(new ChunkCoordinates(World.Camera.Position)) <= RenderDistance / 2); if (newChunk) { ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border | ScheduleType.Lighting); } } finally { //Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }
private bool ProcessQueue() { var maxThreads = Options.VideoOptions.ChunkThreads.Value; if (Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } //maxThreads = Math.Max(1, Math.Min(Options.VideoOptions.ChunkThreads, EnqueuedChunkUpdates / 4)); if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } //if (Interlocked.Read(ref _threadsRunning) ) Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (!CancellationToken.IsCancellationRequested && queue.TryDequeue(out var chunkCoordinates, cc => IsWithinView(cc, World.Camera))) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { bool newChunk = chunk.IsNew; if (BlockLightCalculations != null) { if (newChunk) { //BlockLightCalculations.Recalculate(chunk); } if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } } //SkyLightCalculator.TryProcess(chunkCoordinates); if (SkyLightCalculator != null) { if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } } chunk.UpdateBuffer(Graphics, World); /* if (newChunk) * { * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border); * }*/ } finally { Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }