Update rendering architecture and resource management

Added a new `Ref<T>` struct for reference semantics.
Added the `RenderGraph` system for managing rendering passes.
Added the `RenderTexture` class for encapsulating GPU resources.
Added `GraphicsBuffer` class for effective GPU resource management.
Changed `CommandList` methods from public to internal for visibility control.
Changed `IRenderPass` interface from internal to public for accessibility.
Changed `GetData<T>()` in `ComponentObject.cs` to return `CompRef<T>`.
Changed `GetComponent<T>()` in `EntityManager.cs` to return `CompRef<T>`.
Changed `GetSingleton<T>()` in `World.cs` to use `CompRef<T>`.
Changed `IQueryTypeParameter` to use `CompRef<T>` for consistency.
Changed `QueryItem<T0>` and related structs to use `CompRef<T>`.
Changed `Material` class to support bindless textures.
Changed `Shader` class to support bindless rendering.
Changed `Mesh` class to support bindless vertex and index buffer access.
Updated documentation to reflect the new bindless rendering architecture.
This commit is contained in:
2025-08-01 21:34:48 +09:00
parent 1284bb17de
commit eafbfb2fa1
43 changed files with 3845 additions and 2183 deletions

View File

@@ -24,9 +24,14 @@ public static class GraphicsPipeline
}
}
#if DEBUG
private static DebugLayer? s_debugLayer;
#endif
private static GraphicsDevice? s_graphicsDevice;
private static DescriptorAllocator? s_descriptorAllocator;
private static ResourceAllocator? s_resourceAllocator;
private static ResourceUploadBatch? s_uploadBatch;
private static Thread? s_renderThread;
private static FrameResource[]? s_frameResources;
@@ -37,6 +42,7 @@ public static class GraphicsPipeline
private static bool s_initialized;
private static bool s_isRunning;
private static readonly AutoResetEvent s_shutdownEvent = new(false);
internal static uint CPUFenceValue => s_cpuFenceValue;
internal static uint GPUFenceValue => s_gpuFenceValue;
@@ -46,8 +52,25 @@ public static class GraphicsPipeline
internal static ResourceAllocator ResourceAllocator => s_resourceAllocator ?? throw new InvalidOperationException("Resource allocator is not initialized.");
internal static DescriptorAllocator DescriptorAllocator => s_descriptorAllocator ?? throw new InvalidOperationException("Descriptor allocator is not initialized.");
internal static ResourceUploadBatch UploadBatch
{
get
{
if (s_uploadBatch == null)
{
s_uploadBatch = new();
s_uploadBatch.Begin();
}
return s_uploadBatch;
}
}
internal static void Initialize()
{
#if DEBUG
s_debugLayer = new DebugLayer();
#endif
s_graphicsDevice = new GraphicsDevice();
s_descriptorAllocator = new DescriptorAllocator();
s_resourceAllocator = new ResourceAllocator();
@@ -70,25 +93,47 @@ public static class GraphicsPipeline
private static void RenderLoop()
{
var waitHandles = new WaitHandle[2];
waitHandles[1] = s_shutdownEvent;
while (s_isRunning)
{
s_frameIndex = s_gpuFenceValue % _FRAME_COUNT;
var frameResource = s_frameResources![s_frameIndex];
frameResource.cpuReadyEvent.WaitOne();
// Wait for either CPU ready signal or shutdown signal
waitHandles[0] = frameResource.cpuReadyEvent;
var waitResult = WaitHandle.WaitAny(waitHandles);
s_graphicsDevice!.InitializePendingRenderers();
foreach (var renderer in s_graphicsDevice.Renderers)
// If shutdown was signaled or timeout occurred, exit the loop
if (!s_isRunning || waitResult == 1 || waitResult == WaitHandle.WaitTimeout)
{
renderer.ExecutePendingResize();
renderer.Render();
break;
}
s_gpuFenceValue++;
frameResource.gpuReadyEvent.Set();
// Only proceed if CPU ready event was signaled
if (waitResult == 0)
{
s_graphicsDevice!.InitializePendingRenderers();
s_resourceAllocator!.ReleaseTempResource();
s_uploadBatch?.WaitForCompletion(s_uploadBatch.End());
s_uploadBatch?.Dispose();
s_uploadBatch = null;
if (s_graphicsDevice.Renderers.Length > 0)
{
foreach (var renderer in s_graphicsDevice.Renderers)
{
renderer.ExecutePendingResize();
renderer.Render();
}
}
s_gpuFenceValue++;
frameResource.gpuReadyEvent.Set();
s_resourceAllocator!.ReleaseTempResource();
}
}
}
@@ -129,7 +174,18 @@ public static class GraphicsPipeline
internal static void Stop()
{
s_isRunning = false;
s_renderThread?.Join();
s_shutdownEvent.Set();
if (s_renderThread?.Join(TimeSpan.FromSeconds(5)) == false)
{
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
s_renderThread?.Interrupt();
}
s_shutdownEvent.Reset();
}
internal static void Shutdown()
@@ -149,6 +205,10 @@ public static class GraphicsPipeline
s_frameResources = null;
}
#if DEBUG
s_debugLayer?.Dispose();
#endif
s_initialized = false;
}
}