fix(portal): synchronize destination presentation state
This commit is contained in:
parent
4b1bceefbb
commit
e95f55f25b
42 changed files with 2815 additions and 288 deletions
117
src/AcDream.App/Rendering/Wb/MeshUploadCaches.cs
Normal file
117
src/AcDream.App/Rendering/Wb/MeshUploadCaches.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
using System.Collections.Concurrent;
|
||||
using AcDream.Content;
|
||||
|
||||
namespace AcDream.App.Rendering.Wb;
|
||||
|
||||
/// <summary>
|
||||
/// Deduplicated CPU-to-GPU staging queue. One object id may be queued or
|
||||
/// in-flight at a time; a retry retains ownership until upload succeeds or
|
||||
/// exhausts its retry budget.
|
||||
/// </summary>
|
||||
internal sealed class MeshUploadStagingQueue
|
||||
{
|
||||
private readonly ConcurrentQueue<ObjectMeshData> _queue = new();
|
||||
private readonly ConcurrentDictionary<ulong, byte> _ownedIds = new();
|
||||
|
||||
public bool Stage(ObjectMeshData data)
|
||||
{
|
||||
if (!_ownedIds.TryAdd(data.ObjectId, 0))
|
||||
return false;
|
||||
|
||||
data.UploadAttempts = 0;
|
||||
_queue.Enqueue(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryDequeue(out ObjectMeshData? data) => _queue.TryDequeue(out data);
|
||||
|
||||
public void Requeue(ObjectMeshData data) => _queue.Enqueue(data);
|
||||
|
||||
public void Complete(ulong objectId) => _ownedIds.TryRemove(objectId, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logical render-data ownership, deliberately independent from GPU upload
|
||||
/// existence. Completing or repeating an upload never manufactures an owner;
|
||||
/// only a live entity/landblock pin changes this count.
|
||||
/// </summary>
|
||||
internal sealed class MeshOwnershipCounter
|
||||
{
|
||||
private readonly ConcurrentDictionary<ulong, int> _counts = new();
|
||||
|
||||
public int Acquire(ulong id) => _counts.AddOrUpdate(id, 1, (_, count) => count + 1);
|
||||
|
||||
public int Release(ulong id) => _counts.AddOrUpdate(id, 0, (_, count) => Math.Max(0, count - 1));
|
||||
|
||||
public int Count(ulong id) => _counts.TryGetValue(id, out int count) ? count : 0;
|
||||
|
||||
public bool IsOwned(ulong id) => Count(id) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Reports whether freshly uploaded data has a live owner. This is a query,
|
||||
/// not an acquire: upload existence and logical ownership are independent.
|
||||
/// </summary>
|
||||
public bool MarkUploadComplete(ulong id) => IsOwned(id);
|
||||
|
||||
public bool Remove(ulong id) => _counts.TryRemove(id, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bounded prepared-mesh cache. A cache hit is not merely a CPU return value:
|
||||
/// when GPU render data is absent it re-stages that mesh for upload.
|
||||
/// </summary>
|
||||
internal sealed class CpuMeshUploadCache
|
||||
{
|
||||
private readonly Dictionary<ulong, ObjectMeshData> _data = new();
|
||||
private readonly LinkedList<ulong> _lru = new();
|
||||
private readonly int _capacity;
|
||||
|
||||
public CpuMeshUploadCache(int capacity)
|
||||
{
|
||||
if (capacity <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(capacity));
|
||||
_capacity = capacity;
|
||||
}
|
||||
|
||||
public bool TryGetAndStage(
|
||||
ulong id,
|
||||
MeshUploadStagingQueue staging,
|
||||
out ObjectMeshData? data)
|
||||
{
|
||||
lock (_data)
|
||||
{
|
||||
if (!_data.TryGetValue(id, out data))
|
||||
return false;
|
||||
_lru.Remove(id);
|
||||
_lru.AddLast(id);
|
||||
staging.Stage(data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Store(ObjectMeshData data)
|
||||
{
|
||||
lock (_data)
|
||||
{
|
||||
if (!_data.ContainsKey(data.ObjectId) && _data.Count >= _capacity)
|
||||
{
|
||||
ulong oldest = _lru.First!.Value;
|
||||
_lru.RemoveFirst();
|
||||
_data.Remove(oldest);
|
||||
}
|
||||
|
||||
_data[data.ObjectId] = data;
|
||||
_lru.Remove(data.ObjectId);
|
||||
_lru.AddLast(data.ObjectId);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_data)
|
||||
{
|
||||
_data.Clear();
|
||||
_lru.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue