Revert "feat(render): Campaign V slice V4c - move the world draw path onto the RHI"
This reverts commit f353fb53f8.
This commit is contained in:
parent
b537f3a952
commit
543bc79f8a
8 changed files with 1172 additions and 1215 deletions
|
|
@ -680,8 +680,7 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
"WB draw dispatcher",
|
"WB draw dispatcher",
|
||||||
() => new WbDrawDispatcher(
|
() => new WbDrawDispatcher(
|
||||||
d.Gl,
|
d.Gl,
|
||||||
host.GpuDevice,
|
foundation.MeshShader,
|
||||||
host.GpuFrameLifetime,
|
|
||||||
foundation.TextureCache,
|
foundation.TextureCache,
|
||||||
foundation.MeshAdapter,
|
foundation.MeshAdapter,
|
||||||
entitySpawnAdapter,
|
entitySpawnAdapter,
|
||||||
|
|
@ -856,12 +855,10 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
"environment-cell renderer",
|
"environment-cell renderer",
|
||||||
() => new EnvCellRenderer(
|
() => new EnvCellRenderer(
|
||||||
d.Gl,
|
d.Gl,
|
||||||
host.GpuDevice,
|
|
||||||
host.GpuFrameLifetime,
|
|
||||||
foundation.MeshAdapter.MeshManager!,
|
foundation.MeshAdapter.MeshManager!,
|
||||||
envCellFrustum),
|
envCellFrustum),
|
||||||
static value => value.Dispose());
|
static value => value.Dispose());
|
||||||
envCellLease.Resource.Initialize();
|
envCellLease.Resource.Initialize(foundation.MeshShader);
|
||||||
Fault(LivePresentationCompositionPoint.EnvironmentCellsCreated);
|
Fault(LivePresentationCompositionPoint.EnvironmentCellsCreated);
|
||||||
|
|
||||||
var landblockRenderPublisher = new LandblockRenderPublisher(
|
var landblockRenderPublisher = new LandblockRenderPublisher(
|
||||||
|
|
|
||||||
|
|
@ -190,30 +190,6 @@ internal sealed class GlGpuDevice : IGpuDevice
|
||||||
string fragmentPath = Path.Combine(_shadersDirectory, $"{description.Shaders.Name}.frag");
|
string fragmentPath = Path.Combine(_shadersDirectory, $"{description.Shaders.Name}.frag");
|
||||||
string vertexSource = File.ReadAllText(vertexPath);
|
string vertexSource = File.ReadAllText(vertexPath);
|
||||||
string fragmentSource = File.ReadAllText(fragmentPath);
|
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);
|
return new GlGpuPipeline(_gl, Retirement, description, vertexSource, fragmentSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,31 +297,14 @@ internal sealed class GlGpuDevice : IGpuDevice
|
||||||
"only ever renders single-sampled targets.");
|
"only ever renders single-sampled targets.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Campaign V slice V4c: a null Color.Target means "whatever the frame
|
uint framebuffer = 0;
|
||||||
// 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.
|
|
||||||
if (description.Color.Target is { } target)
|
if (description.Color.Target is { } target)
|
||||||
{
|
{
|
||||||
if (target is not GlGpuRenderTarget glTarget)
|
if (target is not GlGpuRenderTarget glTarget)
|
||||||
throw new ArgumentException("The GL backend can only render into a GL render target.");
|
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 clearsColor = description.Color.Load == GpuLoadOp.Clear;
|
||||||
bool clearsDepth = description.Depth is { Load: GpuLoadOp.Clear };
|
bool clearsDepth = description.Depth is { Load: GpuLoadOp.Clear };
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ public static class RenderBootstrap
|
||||||
|
|
||||||
// --- WbDrawDispatcher (GameWindow ~2377-2381) ---
|
// --- WbDrawDispatcher (GameWindow ~2377-2381) ---
|
||||||
var drawDispatcher = new Wb.WbDrawDispatcher(
|
var drawDispatcher = new Wb.WbDrawDispatcher(
|
||||||
gl, gpuDevice, gpuFrameLifetime, textureCache, meshAdapter, entitySpawnAdapter,
|
gl, meshShader, textureCache, meshAdapter, entitySpawnAdapter,
|
||||||
bindless, classificationCache, translucencyFades);
|
bindless, classificationCache, translucencyFades);
|
||||||
drawDispatcher.AlphaToCoverage = opts.Quality.AlphaToCoverage;
|
drawDispatcher.AlphaToCoverage = opts.Quality.AlphaToCoverage;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,16 +52,7 @@ public sealed class Shader : IDisposable
|
||||||
/// preamble cannot simply be prepended — it has to land after that block,
|
/// preamble cannot simply be prepended — it has to land after that block,
|
||||||
/// before the first real declaration.
|
/// before the first real declaration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
private static string InjectPreamble(string source, string preamble)
|
||||||
/// Campaign V slice V4c widened this from <c>private</c> to
|
|
||||||
/// <c>internal</c> so <c>GlGpuDevice.CreatePipeline</c> splices the
|
|
||||||
/// preamble with the SAME code rather than a second copy of the rule.
|
|
||||||
/// mesh_modern needs the preamble (it calls ACDREAM_TEXTURE_HANDLE and
|
|
||||||
/// ACDREAM_UBO_SET), and a pipeline-compiled copy that differed from the
|
|
||||||
/// <see cref="Shader"/>-compiled one by even a line would be a silent
|
|
||||||
/// divergence between two programs that must stay identical.
|
|
||||||
/// </remarks>
|
|
||||||
internal static string InjectPreamble(string source, string preamble)
|
|
||||||
{
|
{
|
||||||
int insertAt = 0;
|
int insertAt = 0;
|
||||||
int lineStart = 0;
|
int lineStart = 0;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -171,23 +171,6 @@ public sealed class GlobalMeshBuffer : IDisposable
|
||||||
|
|
||||||
/// <summary>The index store's raw GL name. See <see cref="VBO"/>.</summary>
|
/// <summary>The index store's raw GL name. See <see cref="VBO"/>.</summary>
|
||||||
public uint IBO => _indexBuffer is null ? 0u : RequireGlBuffer(_indexBuffer).GlName;
|
public uint IBO => _indexBuffer is null ? 0u : RequireGlBuffer(_indexBuffer).GlName;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The vertex store as the arena actually owns it. Campaign V slice V4c's
|
|
||||||
/// draw paths bind this through <c>IGpuPassEncoder.BindVertexBuffer</c>;
|
|
||||||
/// its layout is already byte-identical to
|
|
||||||
/// <c>GpuVertexLayout.WorldMesh</c> (32-byte stride, locations 0/1/2 at
|
|
||||||
/// offsets 0/12/24 — see <see cref="ConfigureVertexAttributes"/>), so the
|
|
||||||
/// pipeline's own VAO describes the same vertices this arena packs.
|
|
||||||
///
|
|
||||||
/// <see cref="VBO"/>/<see cref="IBO"/> survive alongside these because
|
|
||||||
/// <c>ParticleRenderer</c> and <c>ObjectMeshManager</c> still bind the raw
|
|
||||||
/// names; that bridge retires with them, not with this slice.
|
|
||||||
/// </summary>
|
|
||||||
internal IGpuBuffer? VertexStore => _vertexBuffer;
|
|
||||||
|
|
||||||
/// <summary>The index store as the arena owns it. See <see cref="VertexStore"/>.</summary>
|
|
||||||
internal IGpuBuffer? IndexStore => _indexBuffer;
|
|
||||||
internal long UploadCount { get; private set; }
|
internal long UploadCount { get; private set; }
|
||||||
internal long UploadedBytes { get; private set; }
|
internal long UploadedBytes { get; private set; }
|
||||||
internal long CapacityBytes =>
|
internal long CapacityBytes =>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -110,14 +110,14 @@ public class EnvCellRendererTests
|
||||||
{
|
{
|
||||||
// GL and meshManager are null — only valid for pure-data tests (no
|
// GL and meshManager are null — only valid for pure-data tests (no
|
||||||
// Initialize() is called, so no GL calls are made).
|
// Initialize() is called, so no GL calls are made).
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
Assert.True(r.NeedsPrepare);
|
Assert.True(r.NeedsPrepare);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NewRenderer_NotDisposed()
|
public void NewRenderer_NotDisposed()
|
||||||
{
|
{
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
Assert.False(r.IsDisposed);
|
Assert.False(r.IsDisposed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ public class EnvCellRendererTests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RemoveLandblock_NonExistent_DoesNotThrow()
|
public void RemoveLandblock_NonExistent_DoesNotThrow()
|
||||||
{
|
{
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
// Should silently no-op.
|
// Should silently no-op.
|
||||||
r.RemoveLandblock(0xA9B40000u);
|
r.RemoveLandblock(0xA9B40000u);
|
||||||
Assert.True(r.NeedsPrepare);
|
Assert.True(r.NeedsPrepare);
|
||||||
|
|
@ -218,7 +218,7 @@ public class EnvCellRendererTests
|
||||||
// Reflection-based test that drives the private GetPooledList +
|
// Reflection-based test that drives the private GetPooledList +
|
||||||
// _poolIndex/_listPool fields. If a future refactor removes the
|
// _poolIndex/_listPool fields. If a future refactor removes the
|
||||||
// Clear() call, this test fails.
|
// Clear() call, this test fails.
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
|
|
||||||
var type = typeof(EnvCellRenderer);
|
var type = typeof(EnvCellRenderer);
|
||||||
var getPooledListMethod = type.GetMethod("GetPooledList",
|
var getPooledListMethod = type.GetMethod("GetPooledList",
|
||||||
|
|
@ -249,7 +249,7 @@ public class EnvCellRendererTests
|
||||||
{
|
{
|
||||||
// Sanity check for the fresh-list branch. _poolIndex past _listPool.Count
|
// Sanity check for the fresh-list branch. _poolIndex past _listPool.Count
|
||||||
// should produce a brand-new empty list and grow the pool.
|
// should produce a brand-new empty list and grow the pool.
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
|
|
||||||
var type = typeof(EnvCellRenderer);
|
var type = typeof(EnvCellRenderer);
|
||||||
var getPooledListMethod = type.GetMethod("GetPooledList",
|
var getPooledListMethod = type.GetMethod("GetPooledList",
|
||||||
|
|
@ -338,7 +338,7 @@ public class EnvCellRendererTests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NewRenderer_SnapshotGenerationStartsAtZero()
|
public void NewRenderer_SnapshotGenerationStartsAtZero()
|
||||||
{
|
{
|
||||||
var r = new EnvCellRenderer(gl: null!, device: null!, frameSource: null!, meshManager: null!, frustum: new WbFrustum());
|
var r = new EnvCellRenderer(gl: null!, meshManager: null!, frustum: new WbFrustum());
|
||||||
Assert.Equal(0, r.SnapshotGeneration);
|
Assert.Equal(0, r.SnapshotGeneration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue