diff --git a/src/Runtime/Ghost.Core/Ghost.Core.csproj b/src/Runtime/Ghost.Core/Ghost.Core.csproj
index 955be26..85a2d22 100644
--- a/src/Runtime/Ghost.Core/Ghost.Core.csproj
+++ b/src/Runtime/Ghost.Core/Ghost.Core.csproj
@@ -8,26 +8,26 @@
- $(DefineConstants);MHP_ENABLE_SAFETY_CHECKS;MHP_ENABLE_MIMALLOC
+ $(DefineConstants);MHP_ENABLE_SAFETY_CHECKS;MHP_ENABLE_STACKTRACE;MHP_ENABLE_MIMALLOC;MHP_FASTMATH
True
True
- $(DefineConstants);MHP_ENABLE_MIMALLOC
+ $(DefineConstants);MHP_ENABLE_MIMALLOC;MHP_FASTMATH
True
True
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/Runtime/Ghost.Engine/AssetManager.cs b/src/Runtime/Ghost.Engine/AssetManager.cs
index 22047c1..229278c 100644
--- a/src/Runtime/Ghost.Engine/AssetManager.cs
+++ b/src/Runtime/Ghost.Engine/AssetManager.cs
@@ -1,7 +1,6 @@
using Ghost.Core;
using Ghost.Core.Utilities;
using Ghost.Graphics;
-using Ghost.Graphics.Core;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.Jobs;
using Misaki.HighPerformance.LowLevel;
@@ -54,7 +53,7 @@ internal partial class AssetEntry
{
private static readonly Action[] s_onCreation = new Action[(int)AssetType.Unknown + 1];
private static readonly Func[] s_onParseRawData = new Func[(int)AssetType.Unknown + 1];
- private static readonly Action[] s_onRecordUpload = new Action[(int)AssetType.Unknown + 1];
+ private static readonly Func[] s_onRecordUpload = new Func[(int)AssetType.Unknown + 1];
private static readonly Action[] s_onUploadComplete = new Action[(int)AssetType.Unknown + 1];
private static readonly Action[] s_onReleaseResource = new Action[(int)AssetType.Unknown + 1];
@@ -184,9 +183,9 @@ internal unsafe partial class AssetEntry
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnRecordUploadCommands(ResourceStreamingContext context)
+ public Result OnRecordUploadCommands(ResourceStreamingContext context)
{
- s_onRecordUpload[(int)_assetType]?.Invoke(this, context);
+ return s_onRecordUpload[(int)_assetType]?.Invoke(this, context) ?? Result.Failure("Unsupported asset type.");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -417,10 +416,10 @@ internal partial class AssetManager : IDisposable
if (Interlocked.CompareExchange(ref entry.StateValue, (int)AssetState.Scheduled, (int)AssetState.Ready) == (int)AssetState.Ready)
{
- // Entry is in Ready state — the old texture is valid and will remain visible.
- // Go directly to Scheduled → Loading → Loaded → Uploading → Ready again.
+ // Entry is in Ready state - the old texture is valid and will remain visible.
+ // Go directly to Scheduled -> Loading -> Loaded -> Uploading -> Ready again.
// The swap cycle in RecordTextureUpload/OnTextureUploadComplete handles the
- // v1 → v2 transition exactly like the fallback → v1 transition.
+ // v1 to v2 transition exactly like the fallback to v1 transition.
EnsureScheduled(entry);
}
else
diff --git a/src/Runtime/Ghost.Engine/ResourceStreamingProcessor.cs b/src/Runtime/Ghost.Engine/ResourceStreamingProcessor.cs
index 37bcafd..87fa371 100644
--- a/src/Runtime/Ghost.Engine/ResourceStreamingProcessor.cs
+++ b/src/Runtime/Ghost.Engine/ResourceStreamingProcessor.cs
@@ -62,17 +62,26 @@ internal class ResourceStreamingProcessor : IResourceStreamingProcessor
}
// Record copy commands into cmdCopy
- entry.OnRecordUploadCommands(context);
+ if (entry.OnRecordUploadCommands(context).IsFailure)
+ {
+ Logger.Error($"Failed to record upload commands for asset {entry.AssetId}. Skipping upload.");
+ continue;
+ }
+
entry.State = AssetState.Uploading;
_pendingFinalize.Enqueue(entry);
uploadCount++;
}
- var result = context.CopyPipeline.End();
-
// 3. Submit the batch
- if (uploadCount > 0 && result.IsSuccess)
+ if (context.CopyPipeline.End().IsFailure)
+ {
+ Logger.Error("Failed to submit copy command list for resource streaming.");
+ return;
+ }
+
+ if (uploadCount > 0)
{
_pendingCopyFenceValue = context.CopyPipeline.SignaledFenceValue();
}
diff --git a/src/Runtime/Ghost.Graphics/AssemblyInfo.cs b/src/Runtime/Ghost.Graphics/AssemblyInfo.cs
index 650dddd..67789d0 100644
--- a/src/Runtime/Ghost.Graphics/AssemblyInfo.cs
+++ b/src/Runtime/Ghost.Graphics/AssemblyInfo.cs
@@ -5,6 +5,6 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Ghost.Editor")]
[assembly: InternalsVisibleTo("Ghost.Editor.Core")]
[assembly: InternalsVisibleTo("Ghost.Graphics.Test")]
-[assembly: InternalsVisibleTo("Ghost.Graphics.Test-Winui")]
+[assembly: InternalsVisibleTo("Ghost.UnitTest")]
[assembly: EngineAssembly]
\ No newline at end of file
diff --git a/src/Runtime/Ghost.Graphics/IResourceStreamingProcessor.cs b/src/Runtime/Ghost.Graphics/IResourceStreamingProcessor.cs
index 292a220..b8c546a 100644
--- a/src/Runtime/Ghost.Graphics/IResourceStreamingProcessor.cs
+++ b/src/Runtime/Ghost.Graphics/IResourceStreamingProcessor.cs
@@ -3,7 +3,7 @@ using Ghost.Graphics.Services;
namespace Ghost.Graphics;
-internal ref struct ResourceStreamingContext
+internal readonly struct ResourceStreamingContext
{
public required AsyncCopyPipeline CopyPipeline
{
diff --git a/src/Runtime/Ghost.Graphics/RenderSystem.cs b/src/Runtime/Ghost.Graphics/RenderSystem.cs
index b8aec1f..a8b5968 100644
--- a/src/Runtime/Ghost.Graphics/RenderSystem.cs
+++ b/src/Runtime/Ghost.Graphics/RenderSystem.cs
@@ -475,8 +475,12 @@ public class RenderSystem : IDisposable
_renderPipeline.Dispose();
+ _fence.Dispose();
+
+ _shaderLibrary.Dispose();
_resourceManager.Dispose();
_swapChainManager.Dispose();
+ _asyncCopyPipeline.Dispose();
_graphicsEngine.Dispose();
diff --git a/src/Runtime/Ghost.Graphics/Services/AsyncCopyPipeline.cs b/src/Runtime/Ghost.Graphics/Services/AsyncCopyPipeline.cs
index 9204a34..3ccc09c 100644
--- a/src/Runtime/Ghost.Graphics/Services/AsyncCopyPipeline.cs
+++ b/src/Runtime/Ghost.Graphics/Services/AsyncCopyPipeline.cs
@@ -3,7 +3,7 @@ using Ghost.Graphics.RHI;
namespace Ghost.Graphics.Services;
-public class AsyncCopyPipeline
+public class AsyncCopyPipeline : IDisposable
{
private readonly IRenderDevice _device;
@@ -26,6 +26,11 @@ public class AsyncCopyPipeline
_fence.Name = "AsyncCopyPipeline_Fence";
}
+ ~AsyncCopyPipeline()
+ {
+ Dispose();
+ }
+
internal void Begin()
{
_commandAllocator.Reset();
@@ -74,4 +79,13 @@ public class AsyncCopyPipeline
{
return _fence.WaitForValueAsync(_fenceValue);
}
+
+ public void Dispose()
+ {
+ _commandAllocator.Dispose();
+ _commandBuffer.Dispose();
+ _fence.Dispose();
+
+ GC.SuppressFinalize(this);
+ }
}
diff --git a/src/Runtime/Ghost.Graphics/Services/ResourceManager.cs b/src/Runtime/Ghost.Graphics/Services/ResourceManager.cs
index 0f67e3e..12ea2bc 100644
--- a/src/Runtime/Ghost.Graphics/Services/ResourceManager.cs
+++ b/src/Runtime/Ghost.Graphics/Services/ResourceManager.cs
@@ -592,6 +592,7 @@ public sealed partial class ResourceManager : IDisposable
_meshes.Dispose();
_materials.Dispose();
_shaders.Dispose();
+ _computeShaders.Dispose();
_materialPalettes.Dispose();
_resourceDatabase.ReleaseResource(_paletteOffsetBuffer.AsResource());
diff --git a/src/Test/Ghost.UnitTest/AssetSystem/AssetManagerTest.cs b/src/Test/Ghost.UnitTest/AssetSystem/AssetManagerTest.cs
index 4f27c5f..b19862b 100644
--- a/src/Test/Ghost.UnitTest/AssetSystem/AssetManagerTest.cs
+++ b/src/Test/Ghost.UnitTest/AssetSystem/AssetManagerTest.cs
@@ -1,41 +1,56 @@
+using Ghost.Core;
using Ghost.Engine;
+using Ghost.Graphics;
+using Ghost.Graphics.RHI;
+using Ghost.Graphics.Services;
using Ghost.UnitTest.MockingEnvironment;
using Misaki.HighPerformance.Jobs;
+using Misaki.HighPerformance.LowLevel.Buffer;
namespace Ghost.UnitTest.AssetSystem;
[TestClass]
+[DoNotParallelize]
public class AssetManagerTest
{
- private MockingResourceDatabase _resourceDatabase = null!;
- private MockingResourceAllocator _resourceAllocator = null!;
+ private MockingGraphicsEngine _graphicsEngine = null!;
private MockingCommandBuffer _commandBuffer = null!;
private MockingContentProvider _provider = null!;
+ private AsyncCopyPipeline _copyPipeline = null!;
+ private ResourceManager _resourceManager = null!;
private ResourceStreamingProcessor _processor = null!;
private JobScheduler _jobScheduler = null!;
private AssetManager _assetManager = null!;
+ public TestContext TestContext
+ {
+ get; set;
+ }
+
[TestInitialize]
public void Setup()
{
- _resourceDatabase = new MockingResourceDatabase();
- _resourceAllocator = new MockingResourceAllocator(_resourceDatabase);
- _commandBuffer = new MockingCommandBuffer(_resourceDatabase);
+ AllocationManager.Initialize(AllocationManagerDesc.Default);
+
+ _graphicsEngine = new MockingGraphicsEngine();
+ _commandBuffer = (MockingCommandBuffer)_graphicsEngine.CreateCommandBuffer();
_provider = new MockingContentProvider();
+ _copyPipeline = new AsyncCopyPipeline(_graphicsEngine);
+ _resourceManager = new ResourceManager(_graphicsEngine.Device, _graphicsEngine.ResourceAllocator, _graphicsEngine.ResourceDatabase);
_processor = new ResourceStreamingProcessor();
var schedulerDesc = new JobSchedulerDesc
{
ThreadCount = 1,
ThreadPriority = ThreadPriority.Normal,
- DependencyChainCapacity = 1024,
+ DependencyChainCapacity = 64,
};
_jobScheduler = new JobScheduler(in schedulerDesc);
- _assetManager = new AssetManager(_resourceDatabase, _provider, _processor, _jobScheduler);
+ _assetManager = new AssetManager(_graphicsEngine.ResourceDatabase, _provider, _processor, _jobScheduler);
}
[TestCleanup]
@@ -43,18 +58,55 @@ public class AssetManagerTest
{
_assetManager.Dispose();
_jobScheduler.Dispose();
+ _resourceManager.Dispose();
+ _copyPipeline.Dispose();
_commandBuffer.Dispose();
- _resourceAllocator.Dispose();
- _resourceDatabase.Dispose();
+ _graphicsEngine.Dispose();
+
+ AllocationManager.Dispose();
}
[TestMethod]
- public void AssetManager_GetsAssetSuccessfully()
+ public async Task AssetManager_ResolveTextureThenBackgroundUpload()
{
var assetID = Guid.NewGuid();
_provider.AddMockTexture(assetID, readDelayMs: Random.Shared.Next(10, 50));
var handle = _assetManager.ResolveTexture(assetID);
Assert.IsTrue(handle.IsValid);
+
+ Assert.IsTrue(_assetManager.TryGetEntry(assetID, out var entry));
+ Assert.IsGreaterThanOrEqualTo((int)AssetState.Scheduled, entry.StateValue);
+
+ await Task.Delay(1000, TestContext.CancellationToken);
+
+ Assert.IsGreaterThanOrEqualTo((int)AssetState.Loaded, entry.StateValue);
+
+ var ctx = new ResourceStreamingContext
+ {
+ ResourceManager = _resourceManager,
+ ResourceDatabase = _graphicsEngine.ResourceDatabase,
+ ResourceAllocator = _graphicsEngine.ResourceAllocator,
+ CopyPipeline = _copyPipeline,
+ GraphicsCommandBuffer = _commandBuffer,
+ };
+
+ _processor.ProcessPendingUploads(ctx);
+
+ await Task.Delay(1000, TestContext.CancellationToken);
+
+ Assert.IsGreaterThanOrEqualTo((int)AssetState.Uploading, entry.StateValue);
+
+ // Trigger the completion of the upload and the transition to shader resource state.
+ _processor.ProcessPendingUploads(ctx);
+
+ Assert.IsGreaterThanOrEqualTo((int)AssetState.Ready, entry.StateValue);
+
+ var (data, error) = _graphicsEngine.ResourceDatabase.GetResourceBarrierData(handle.AsResource());
+
+ Assert.AreEqual(Error.None, error);
+ Assert.AreEqual(BarrierAccess.ShaderResource, data.access);
+ Assert.AreEqual(BarrierLayout.ShaderResource, data.layout);
+ Assert.AreEqual(BarrierSync.AllShading, data.sync);
}
}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandAllocator.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandAllocator.cs
new file mode 100644
index 0000000..37d6763
--- /dev/null
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandAllocator.cs
@@ -0,0 +1,19 @@
+using Ghost.Graphics.RHI;
+
+namespace Ghost.UnitTest.MockingEnvironment;
+
+internal class MockingCommandAllocator : ICommandAllocator
+{
+ public string Name
+ {
+ get; set;
+ } = "MockCommandAllocator";
+
+ public void Reset()
+ {
+ }
+
+ public void Dispose()
+ {
+ }
+}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandBuffer.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandBuffer.cs
index 67778fc..9a06c84 100644
--- a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandBuffer.cs
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandBuffer.cs
@@ -8,7 +8,6 @@ internal class MockingCommandBuffer : ICommandBuffer
{
private readonly IResourceDatabase _resourceDatabase;
- private string _name = "MockCommandBuffer";
private bool _isEmpty = true;
// Tracking properties for test assertions
@@ -16,19 +15,22 @@ internal class MockingCommandBuffer : ICommandBuffer
public int CopyCallCount { get; private set; }
public int UpdateSubResourcesCount { get; private set; }
- public CommandBufferType Type => default;
-
public bool IsEmpty => _isEmpty;
+ public CommandBufferType Type
+ {
+ get;
+ }
+
public string Name
{
- get => _name;
- set => _name = value;
- }
+ get; set;
+ } = "MockingCommandBuffer";
- public MockingCommandBuffer(IResourceDatabase resourceDatabase)
+ public MockingCommandBuffer(IResourceDatabase resourceDatabase, CommandBufferType type)
{
_resourceDatabase = resourceDatabase;
+ Type = type;
}
public void Barrier(params scoped ReadOnlySpan barrierDescs)
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandQueue.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandQueue.cs
new file mode 100644
index 0000000..16777d0
--- /dev/null
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingCommandQueue.cs
@@ -0,0 +1,48 @@
+using Ghost.Graphics.RHI;
+using System.Diagnostics;
+
+namespace Ghost.UnitTest.MockingEnvironment;
+
+internal class MockingCommandQueue : ICommandQueue
+{
+ public CommandQueueType Type
+ {
+ get;
+ }
+
+ public string Name
+ {
+ get; set;
+ } = "MockCommandQueue";
+
+ public MockingCommandQueue(CommandQueueType type)
+ {
+ Type = type;
+ }
+
+ public ulong Signal(IFence fence, ulong value)
+ {
+ var mockingFence = fence as MockingFence;
+ Debug.Assert(mockingFence != null);
+
+ mockingFence.Signal(value);
+ return value;
+ }
+
+ public void Submit(ICommandBuffer commandBuffer)
+ {
+ }
+
+ public void Submit(params scoped ReadOnlySpan commandBuffers)
+ {
+ }
+
+ public void Wait(IFence fence, ulong value)
+ {
+ Thread.Sleep(Random.Shared.Next(10, 50));
+ }
+
+ public void Dispose()
+ {
+ }
+}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingFence.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingFence.cs
new file mode 100644
index 0000000..fbe9574
--- /dev/null
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingFence.cs
@@ -0,0 +1,52 @@
+using Ghost.Graphics.RHI;
+
+namespace Ghost.UnitTest.MockingEnvironment;
+
+internal class MockingFence : IFence
+{
+ private readonly AutoResetEvent _fenceEvent;
+
+ private ulong _currentValue;
+
+ public ulong CompletedValue => _currentValue;
+
+ public nint WaitHandle => _fenceEvent.SafeWaitHandle.DangerousGetHandle();
+
+ public string Name
+ {
+ get; set;
+ } = "MockingFence";
+
+ public MockingFence(ulong initialValue)
+ {
+ _fenceEvent = new AutoResetEvent(false);
+ _currentValue = initialValue;
+ }
+
+ public void Signal(ulong value)
+ {
+ if (value > _currentValue)
+ {
+ _currentValue = value;
+ _fenceEvent.Set();
+ }
+ }
+
+ public void WaitForValue(ulong value)
+ {
+ if (value > _currentValue)
+ {
+ _fenceEvent.WaitOne();
+ }
+ }
+
+ public Task WaitForValueAsync(ulong value)
+ {
+ return Task.Run(() => { WaitForValue(value); });
+ }
+
+ public void Dispose()
+ {
+ _fenceEvent.Dispose();
+ }
+}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingGraphicsEngine.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingGraphicsEngine.cs
new file mode 100644
index 0000000..84ffe90
--- /dev/null
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingGraphicsEngine.cs
@@ -0,0 +1,72 @@
+using Ghost.Graphics.RHI;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Ghost.UnitTest.MockingEnvironment;
+
+internal class MockingGraphicsEngine : IGraphicsEngine
+{
+ private readonly MockingRenderDevice _renderDevice;
+ private readonly MockingResourceDatabase _resourceDatabase;
+ private readonly MockingResourceAllocator _resourceAllocator;
+
+ public IRenderDevice Device => _renderDevice;
+
+ public IPipelineLibrary PipelineLibrary => throw new NotImplementedException();
+
+ public IResourceDatabase ResourceDatabase => _resourceDatabase;
+
+ public IResourceAllocator ResourceAllocator => _resourceAllocator;
+
+ public MockingGraphicsEngine()
+ {
+ _renderDevice = new MockingRenderDevice();
+ _resourceDatabase = new MockingResourceDatabase();
+ _resourceAllocator = new MockingResourceAllocator(_resourceDatabase);
+ }
+
+ public void BeginFrame(ulong submittedFrame)
+ {
+ }
+
+ public ICommandAllocator CreateCommandAllocator(CommandBufferType type = CommandBufferType.Graphics)
+ {
+ return new MockingCommandAllocator();
+ }
+
+ public ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics)
+ {
+ return new MockingCommandBuffer(_resourceDatabase, type);
+ }
+
+ public IFence CreateFence(ulong initialValue = 0)
+ {
+ return new MockingFence(initialValue);
+ }
+
+ public ISwapChain CreateSwapChain(SwapChainDesc desc)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void EndFrame(ulong completedFrame)
+ {
+ }
+
+ public ICommandBuffer GetPooledCommandBuffer(CommandBufferType type = CommandBufferType.Graphics)
+ {
+ return new MockingCommandBuffer(_resourceDatabase, type);
+ }
+
+ public void ReturnPooledCommandBuffer(ICommandBuffer commandBuffer)
+ {
+ }
+
+ public void Dispose()
+ {
+ _resourceAllocator.Dispose();
+ _resourceDatabase.Dispose();
+ _renderDevice.Dispose();
+ }
+}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingRenderDevice.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingRenderDevice.cs
new file mode 100644
index 0000000..f1e1e61
--- /dev/null
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingRenderDevice.cs
@@ -0,0 +1,27 @@
+using Ghost.Graphics.RHI;
+
+namespace Ghost.UnitTest.MockingEnvironment;
+
+internal class MockingRenderDevice : IRenderDevice
+{
+ private readonly MockingCommandQueue _commandQueue = new MockingCommandQueue(CommandQueueType.Graphics);
+ private readonly MockingCommandQueue _computeCommandQueue = new MockingCommandQueue(CommandQueueType.Compute);
+ private readonly MockingCommandQueue _copyCommandQueue = new MockingCommandQueue(CommandQueueType.Copy);
+
+ public ICommandQueue GraphicsQueue => _commandQueue;
+
+ public ICommandQueue ComputeQueue => _computeCommandQueue;
+
+ public ICommandQueue CopyQueue => _copyCommandQueue;
+
+ public FeatureSupport FeatureSupport => (FeatureSupport)~0;
+
+ public string Name
+ {
+ get; set;
+ } = "MockingRenderDevice";
+
+ public void Dispose()
+ {
+ }
+}
diff --git a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingResourceDatabase.cs b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingResourceDatabase.cs
index e7b309e..7013beb 100644
--- a/src/Test/Ghost.UnitTest/MockingEnvironment/MockingResourceDatabase.cs
+++ b/src/Test/Ghost.UnitTest/MockingEnvironment/MockingResourceDatabase.cs
@@ -21,7 +21,6 @@ internal unsafe class MockingResourceDatabase : IResourceDatabase
private int _samplerToken = 0;
private static ulong GetKey(Handle handle) => ((ulong)handle.Generation << 32) | (uint)handle.ID;
- private static ulong GetKey(Handle handle) where T : unmanaged => ((ulong)handle.Generation << 32) | (uint)handle.ID;
public Handle AddMockResource(ResourceDesc desc, ResourceBarrierData barrierData, string? name)
{
@@ -88,7 +87,7 @@ internal unsafe class MockingResourceDatabase : IResourceDatabase
public ulong GetIntermediateResourceSize(Handle resource, uint firstSubResource, uint numSubResources)
{
- return 1024 * 1024; // Mock size 1MB
+ return 0; // For testing, we can return 0 because we don't actually allocate memory.
}
public Result GetResourceBarrierData(Handle handle)
@@ -151,9 +150,15 @@ internal unsafe class MockingResourceDatabase : IResourceDatabase
public Handle Replace(Handle dst, Handle src)
{
- // For tests, replacing means taking the new handle (src) and disposing the old (dst)
- ReleaseResource(dst);
- return src;
+ if (_resources.TryGetValue(GetKey(dst), out var recordDst) &&
+ _resources.TryGetValue(GetKey(src), out var recordSrc))
+ {
+ _resources[GetKey(dst)] = recordSrc;
+ _resources[GetKey(src)] = recordDst;
+ }
+
+ ReleaseResource(src);
+ return dst;
}
public Error SetResourceBarrierData(Handle handle, ResourceBarrierData data)
@@ -164,8 +169,10 @@ internal unsafe class MockingResourceDatabase : IResourceDatabase
{
record.barrierData = data;
}
+
return Error.None;
}
+
return Error.NotFound;
}