refactor(app): compose world rendering startup

Move Region/environment, mandatory modern rendering, terrain, WB, texture, and sampler construction behind the typed Phase-4 composition boundary. Give every fallible GL constructor prefix retryable ownership so partial startup failure cannot leak or replay resource deletion while preserving the accepted render path and DAT inputs.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 16:46:05 +02:00
parent cd7b519f78
commit 6a2fe98cc4
22 changed files with 1983 additions and 634 deletions

View file

@ -20,6 +20,7 @@ public sealed unsafe class DebugLineRenderer : IDisposable
private readonly Shader _shader;
private readonly uint _vao;
private readonly uint _vbo;
private readonly ResourceCleanupGroup _resources;
private readonly List<float> _buffer = new(4096);
private int _vertexCount;
@ -27,25 +28,67 @@ public sealed unsafe class DebugLineRenderer : IDisposable
public DebugLineRenderer(GL gl, string shaderDir)
{
_gl = gl;
_shader = new Shader(gl,
Path.Combine(shaderDir, "debug_line.vert"),
Path.Combine(shaderDir, "debug_line.frag"));
_gl = gl ?? throw new ArgumentNullException(nameof(gl));
ArgumentException.ThrowIfNullOrWhiteSpace(shaderDir);
var resources = new ResourceCleanupGroup();
Shader? shader = null;
uint vao = 0;
uint vbo = 0;
try
{
shader = new Shader(gl,
Path.Combine(shaderDir, "debug_line.vert"),
Path.Combine(shaderDir, "debug_line.frag"));
resources.Add("debug-line shader", shader.Dispose);
vao = GlResourceCommand.CreateName(
gl,
"debug-line VAO",
gl.GenVertexArray,
gl.DeleteVertexArray);
uint ownedVao = vao;
resources.Add(
"debug-line VAO",
() => GlResourceCommand.DeleteVertexArray(
gl,
ownedVao,
$"delete debug-line VAO {ownedVao}"));
vbo = GlResourceCommand.CreateName(
gl,
"debug-line VBO",
gl.GenBuffer,
gl.DeleteBuffer);
uint ownedVbo = vbo;
resources.Add(
"debug-line VBO",
() => GlResourceCommand.DeleteBuffer(
gl,
ownedVbo,
$"delete debug-line VBO {ownedVbo}"));
_vao = _gl.GenVertexArray();
_vbo = _gl.GenBuffer();
GlResourceCommand.Execute(gl, "configure debug-line vertex state", () =>
{
gl.BindVertexArray(vao);
gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);
// 24-byte stride: vec3 pos + vec3 color
gl.EnableVertexAttribArray(0);
gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);
gl.EnableVertexAttribArray(1);
gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));
gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
gl.BindVertexArray(0);
});
}
catch (Exception constructionFailure)
{
resources.RollbackConstructionAndThrow(
"DebugLineRenderer construction failed and its GL prefix did not cleanly roll back.",
constructionFailure);
}
_gl.BindVertexArray(_vao);
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vbo);
// 24-byte stride: vec3 pos + vec3 color
_gl.EnableVertexAttribArray(0);
_gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);
_gl.EnableVertexAttribArray(1);
_gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
_gl.BindVertexArray(0);
_resources = resources;
_shader = shader!;
_vao = vao;
_vbo = vbo;
}
/// <summary>Clear accumulated lines. Call at the start of each frame.</summary>
@ -165,8 +208,6 @@ public sealed unsafe class DebugLineRenderer : IDisposable
public void Dispose()
{
_gl.DeleteVertexArray(_vao);
_gl.DeleteBuffer(_vbo);
_shader.Dispose();
_resources.RetryCleanup();
}
}