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:
parent
cd7b519f78
commit
6a2fe98cc4
22 changed files with 1983 additions and 634 deletions
|
|
@ -88,6 +88,7 @@ void main() { } // depth-only: color writes are masked off by the caller state
|
|||
private readonly int _locForceFarZ;
|
||||
private readonly int _locDepthBias;
|
||||
private readonly int _locDepthBiasEyeCapN;
|
||||
private readonly ResourceCleanupGroup _resources;
|
||||
|
||||
private const int MaxFanVerts = 32;
|
||||
private readonly float[] _scratch = new float[MaxFanVerts * 3];
|
||||
|
|
@ -109,28 +110,52 @@ void main() { } // depth-only: color writes are masked off by the caller state
|
|||
public PortalDepthMaskRenderer(GL gl)
|
||||
{
|
||||
_gl = gl ?? throw new ArgumentNullException(nameof(gl));
|
||||
var resources = new ResourceCleanupGroup();
|
||||
try
|
||||
{
|
||||
_program = ShaderProgramConstruction.Build(
|
||||
new GlShaderProgramBuildApi(gl),
|
||||
VertSrc,
|
||||
FragSrc);
|
||||
resources.Add(
|
||||
"portal-depth program",
|
||||
() => GlResourceCommand.DeleteProgram(
|
||||
gl,
|
||||
_program,
|
||||
$"delete PortalDepthMask program {_program}"));
|
||||
|
||||
uint vs = Compile(ShaderType.VertexShader, VertSrc);
|
||||
uint fs = Compile(ShaderType.FragmentShader, FragSrc);
|
||||
_program = _gl.CreateProgram();
|
||||
_gl.AttachShader(_program, vs);
|
||||
_gl.AttachShader(_program, fs);
|
||||
_gl.LinkProgram(_program);
|
||||
_gl.GetProgram(_program, ProgramPropertyARB.LinkStatus, out int linked);
|
||||
if (linked == 0)
|
||||
throw new InvalidOperationException($"PortalDepthMask link failed: {_gl.GetProgramInfoLog(_program)}");
|
||||
_gl.DeleteShader(vs);
|
||||
_gl.DeleteShader(fs);
|
||||
(
|
||||
_locViewProjection,
|
||||
_locPlaneCount,
|
||||
_locPlanes,
|
||||
_locForceFarZ,
|
||||
_locDepthBias,
|
||||
_locDepthBiasEyeCapN) = GlResourceCommand.Execute(
|
||||
_gl,
|
||||
"resolve PortalDepthMask uniforms",
|
||||
() => (
|
||||
_gl.GetUniformLocation(_program, "uViewProjection"),
|
||||
_gl.GetUniformLocation(_program, "uPlaneCount"),
|
||||
_gl.GetUniformLocation(_program, "uPlanes"),
|
||||
_gl.GetUniformLocation(_program, "uForceFarZ"),
|
||||
_gl.GetUniformLocation(_program, "uDepthBias"),
|
||||
_gl.GetUniformLocation(_program, "uDepthBiasEyeCapN")));
|
||||
|
||||
_locViewProjection = _gl.GetUniformLocation(_program, "uViewProjection");
|
||||
_locPlaneCount = _gl.GetUniformLocation(_program, "uPlaneCount");
|
||||
_locPlanes = _gl.GetUniformLocation(_program, "uPlanes");
|
||||
_locForceFarZ = _gl.GetUniformLocation(_program, "uForceFarZ");
|
||||
_locDepthBias = _gl.GetUniformLocation(_program, "uDepthBias");
|
||||
_locDepthBiasEyeCapN = _gl.GetUniformLocation(_program, "uDepthBiasEyeCapN");
|
||||
for (int i = 0; i < _frameBuffers.Length; i++)
|
||||
{
|
||||
FrameBufferSet set = CreateFrameBufferSet(resources, i);
|
||||
_frameBuffers[i] = set;
|
||||
}
|
||||
}
|
||||
catch (Exception constructionFailure)
|
||||
{
|
||||
resources.RollbackConstructionAndThrow(
|
||||
"PortalDepthMaskRenderer construction failed and its GL prefix did not cleanly roll back.",
|
||||
constructionFailure);
|
||||
throw new System.Diagnostics.UnreachableException();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _frameBuffers.Length; i++)
|
||||
_frameBuffers[i] = CreateFrameBufferSet();
|
||||
_resources = resources;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -146,19 +171,34 @@ void main() { } // depth-only: color writes are masked off by the caller state
|
|||
_activeFrameBuffer.UsedVertices = 0;
|
||||
}
|
||||
|
||||
private FrameBufferSet CreateFrameBufferSet()
|
||||
private FrameBufferSet CreateFrameBufferSet(
|
||||
ResourceCleanupGroup resources,
|
||||
int frameIndex)
|
||||
{
|
||||
uint vao = 0;
|
||||
uint vbo = 0;
|
||||
try
|
||||
uint vao = TrackedGlResource.CreateVertexArray(
|
||||
_gl,
|
||||
"PortalDepthMask frame VAO creation");
|
||||
RetryableGpuResourceRelease vaoRelease =
|
||||
TrackedGlResource.CreateRetryableVertexArrayDeletion(
|
||||
_gl,
|
||||
vao,
|
||||
"PortalDepthMask frame VAO disposal");
|
||||
resources.Add($"portal-depth frame {frameIndex} VAO", vaoRelease.Run);
|
||||
|
||||
uint vbo = TrackedGlResource.CreateBuffer(
|
||||
_gl,
|
||||
"PortalDepthMask frame VBO creation");
|
||||
var set = new FrameBufferSet { Vao = vao, Vbo = vbo };
|
||||
RetryableGpuResourceRelease vboRelease =
|
||||
TrackedGlResource.CreateRetryableBufferDeletion(
|
||||
_gl,
|
||||
vbo,
|
||||
() => set.CapacityBytes,
|
||||
"PortalDepthMask frame VBO disposal");
|
||||
resources.Add($"portal-depth frame {frameIndex} VBO", vboRelease.Run);
|
||||
|
||||
GlResourceCommand.Execute(_gl, "configure PortalDepthMask frame buffers", () =>
|
||||
{
|
||||
vao = TrackedGlResource.CreateVertexArray(
|
||||
_gl,
|
||||
"PortalDepthMask frame VAO creation");
|
||||
vbo = TrackedGlResource.CreateBuffer(
|
||||
_gl,
|
||||
"PortalDepthMask frame VBO creation");
|
||||
var set = new FrameBufferSet { Vao = vao, Vbo = vbo };
|
||||
_gl.BindVertexArray(set.Vao);
|
||||
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, set.Vbo);
|
||||
unsafe
|
||||
|
|
@ -168,29 +208,8 @@ void main() { } // depth-only: color writes are masked off by the caller state
|
|||
_gl.EnableVertexAttribArray(0);
|
||||
_gl.BindVertexArray(0);
|
||||
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
|
||||
return set;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (vbo != 0)
|
||||
TrackedGlResource.DeleteBuffer(
|
||||
_gl, vbo, 0, "PortalDepthMask frame VBO rollback");
|
||||
if (vao != 0)
|
||||
TrackedGlResource.DeleteVertexArray(
|
||||
_gl, vao, "PortalDepthMask frame VAO rollback");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private uint Compile(ShaderType type, string src)
|
||||
{
|
||||
uint s = _gl.CreateShader(type);
|
||||
_gl.ShaderSource(s, src);
|
||||
_gl.CompileShader(s);
|
||||
_gl.GetShader(s, ShaderParameterName.CompileStatus, out int ok);
|
||||
if (ok == 0)
|
||||
throw new InvalidOperationException($"PortalDepthMask {type} compile failed: {_gl.GetShaderInfoLog(s)}");
|
||||
return s;
|
||||
});
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -387,18 +406,6 @@ void main() { } // depth-only: color writes are masked off by the caller state
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_gl.DeleteProgram(_program);
|
||||
foreach (FrameBufferSet set in _frameBuffers)
|
||||
{
|
||||
TrackedGlResource.DeleteVertexArray(
|
||||
_gl,
|
||||
set.Vao,
|
||||
"PortalDepthMask frame VAO disposal");
|
||||
TrackedGlResource.DeleteBuffer(
|
||||
_gl,
|
||||
set.Vbo,
|
||||
set.CapacityBytes,
|
||||
"PortalDepthMask frame VBO disposal");
|
||||
}
|
||||
_resources.RetryCleanup();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue