Revert "feat(render): Campaign V slice V4c - move the world draw path onto the RHI"

This reverts commit f353fb53f8.
This commit is contained in:
Erik 2026-07-27 22:38:02 +02:00
parent b537f3a952
commit 543bc79f8a
8 changed files with 1172 additions and 1215 deletions

View file

@ -190,30 +190,6 @@ internal sealed class GlGpuDevice : IGpuDevice
string fragmentPath = Path.Combine(_shadersDirectory, $"{description.Shaders.Name}.frag");
string vertexSource = File.ReadAllText(vertexPath);
string fragmentSource = File.ReadAllText(fragmentPath);
// Campaign V slice V4c: splice the slice-V2 shared preamble
// (Shaders/common.glsl) into every pipeline, using Shader's own
// InjectPreamble so a pipeline-compiled program and a
// Shader-compiled one are built from byte-identical sources.
//
// mesh_modern REQUIRES it — the preamble declares the binding-9
// texture table and defines ACDREAM_TEXTURE_HANDLE / ACDREAM_UBO_SET,
// so without it the world shaders do not compile at all. Applying it
// unconditionally rather than per-pipeline keeps one rule: every
// shader this backend compiles sees the same preamble, which is also
// what the Vulkan backend gets for free once the sources are compiled
// to .spv. For shaders that reference none of it (ui_text,
// debug_line) the added text is an unused SSBO declaration and two
// macro definitions — every shader in the tree is #version 430 core,
// so the std430 declaration is always legal.
string commonPath = Path.Combine(_shadersDirectory, "common.glsl");
if (File.Exists(commonPath))
{
string commonSource = File.ReadAllText(commonPath);
vertexSource = Shader.InjectPreamble(vertexSource, commonSource);
fragmentSource = Shader.InjectPreamble(fragmentSource, commonSource);
}
return new GlGpuPipeline(_gl, Retirement, description, vertexSource, fragmentSource);
}
@ -321,31 +297,14 @@ internal sealed class GlGpuDevice : IGpuDevice
"only ever renders single-sampled targets.");
}
// Campaign V slice V4c: a null Color.Target means "whatever the frame
// spine has bound", NOT "framebuffer 0" — so this deliberately does
// not rebind. GpuPassDescription's own remarks say the transitional
// path keeps "clears and framebuffer management" with the spine, and
// forcing 0 here breaks that: PrivateEntityViewportRenderer binds its
// offscreen FBO and then calls WbDrawDispatcher.Draw (see that file's
// RenderToTexture), as does PortalTunnelPresentation. Once the
// dispatcher records through an encoder, binding 0 on BeginPass would
// redirect the paperdoll and creature-appraisal viewports to the
// backbuffer and leave their textures empty — and the offline pixel
// gate does not cover those viewports, so it would have shipped
// silently. This is the same class of fix as the ambient-capability
// save/restore in GlGpuPassEncoder (plan §7.1 rule 1): while raw-GL
// renderers still own framebuffers, the backend preserves what they
// bound rather than asserting its own. Removed at V4h, when the spine
// declares real passes and a target is always explicit.
//
// An explicit Target still binds, because then the caller HAS named
// the attachment.
uint framebuffer = 0;
if (description.Color.Target is { } target)
{
if (target is not GlGpuRenderTarget glTarget)
throw new ArgumentException("The GL backend can only render into a GL render target.");
_gl.BindFramebuffer(GLEnum.Framebuffer, glTarget.GlFramebufferName);
framebuffer = glTarget.GlFramebufferName;
}
_gl.BindFramebuffer(GLEnum.Framebuffer, framebuffer);
bool clearsColor = description.Color.Load == GpuLoadOp.Clear;
bool clearsDepth = description.Depth is { Load: GpuLoadOp.Clear };