Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core/Render/OpenGL/Renderers/Legacy/World/CoverKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Helion.Render.OpenGL.Renderers.Legacy.World;
readonly struct CoverKey(int key1, int key2) : IEquatable<CoverKey>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static CoverKey MakeCoverWallKey(int sideId, WallLocation location) => new(sideId, (int)location);
public static CoverKey MakeCoverWallKey(int sideId, WallLocation location, bool oneSided) => new(sideId, (int)location * (oneSided ? 1 : 2));

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static CoverKey MakeFlatKey(int sectorId, SectorPlaneFace plane) => new(sectorId, (int)plane);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ public partial class StaticCacheGeometryRenderer : StyleRendererBase, IDisposabl
private GeometryData? m_coverWallGeometryOneSided;
private GeometryData? m_coverFlatGeometry;

private bool m_disposed;
private IWorld m_world = null!;
private bool m_disposed;
private bool m_vanillaRender;
private bool m_worldReload;

public StaticCacheGeometryRenderer(ArchiveCollection archiveCollection, LegacyGLTextureManager textureManager,
RenderProgram program, GeometryRenderer geometryRenderer)
Expand Down Expand Up @@ -103,6 +104,7 @@ public void UpdateTo(IWorld world)
ClearData(world);

m_world = world;
m_worldReload = true;

if (WorldStatic.Sector3D)
m_world.SectorMove += World_SectorMove;
Expand Down Expand Up @@ -180,6 +182,8 @@ public void UpdateTo(IWorld world)
data.Vbo.UploadIfNeeded();
}
}

m_worldReload = false;
}

private void World_SectorFogColorChanged(object? sender, Sector sector)
Expand Down Expand Up @@ -1100,8 +1104,13 @@ private void HandleSectorMoveStart3D(WorldBase world, Sector3D sector3D)
private void ClearSideGeometryVertices(Side side, Wall wall)
{
ClearGeometryVertices(wall.Static);
if (m_vanillaRender && m_coverWallLookup.TryGetValue(CoverKey.MakeCoverWallKey(side.Id, wall.Location), out var geometryData))
ClearGeometryVertices(geometryData);
if (m_vanillaRender)
{
if (m_coverWallLookup.TryGetValue(CoverKey.MakeCoverWallKey(side.Id, wall.Location, true), out var geometryData))
ClearGeometryVertices(geometryData);
if (m_coverWallLookup.TryGetValue(CoverKey.MakeCoverWallKey(side.Id, wall.Location, false), out geometryData))
ClearGeometryVertices(geometryData);
}
}

private void World_SectorMoveComplete(object? sender, SectorPlane plane)
Expand Down Expand Up @@ -1322,8 +1331,16 @@ private void UpdateVertices(ref StaticGeometryData staticGeometry, int textureHa

var startIndex = staticGeometry.Index;
CopyVertices(staticGeometry.GeometryData.Vbo.Data.Data, vertices, startIndex);
staticGeometry.GeometryData.Vbo.Bind();
staticGeometry.GeometryData.Vbo.UploadSubData(startIndex, vertices.Length);

if (m_worldReload)
{
staticGeometry.GeometryData.Vbo.SetNotUploaded();
}
else
{
staticGeometry.GeometryData.Vbo.Bind();
staticGeometry.GeometryData.Vbo.UploadSubData(startIndex, vertices.Length);
}

// On map reloads the Vbo length is cleared. This ensures it's expanded back out correctly.
staticGeometry.GeometryData.Vbo.Data.Length = Math.Max(staticGeometry.GeometryData.Vbo.Data.Length, startIndex + vertices.Length);
Expand All @@ -1334,29 +1351,55 @@ private void AddOrUpdateCoverWall(Side side, Span<DynamicVertex> sideVertices, W
if (m_coverWallGeometry == null || m_coverWallGeometryOneSided == null)
return;

var useGeometry = oneSided ? m_coverWallGeometryOneSided : m_coverWallGeometry;
// This is uploaded as the max possible value so UploadSubData can be used even if it's new.
var vbo = useGeometry.Vbo;
var key = CoverKey.MakeCoverWallKey(side.Id, location);
var key = CoverKey.MakeCoverWallKey(side.Id, location, oneSided);
int length = sideVertices.Length;
if (m_coverWallLookup.TryGetValue(key, out var staticGeometryData))
if (m_coverWallLookup.TryGetValue(key, out var staticGeometryData) && staticGeometryData.GeometryData != null)
{
CoverWallUtil.CopyCoverWallVertices(side, vbo.Data.Data, sideVertices, staticGeometryData.Index, location);
vbo.Bind();
vbo.UploadSubData(staticGeometryData.Index, length);
return;
var geometryVbo = staticGeometryData.GeometryData.Vbo;
EnsureCoverWallVboCapacity(staticGeometryData, sideVertices, geometryVbo);

CoverWallUtil.CopyCoverWallVertices(side, geometryVbo.Data.Data, sideVertices, staticGeometryData.Index, location);
if (m_worldReload)
{
geometryVbo.SetNotUploaded();
}
else
{
geometryVbo.Bind();
geometryVbo.UploadSubData(staticGeometryData.Index, length);
}
}
else
{
var useGeometry = oneSided ? m_coverWallGeometryOneSided : m_coverWallGeometry;
var geometryVbo = useGeometry.Vbo;
EnsureCoverWallVboCapacity(staticGeometryData, sideVertices, geometryVbo);
var vertices = geometryVbo.Data;
geometryVbo.Data.EnsureCapacity(vertices.Length + sideVertices.Length);
staticGeometryData = new(useGeometry, vertices.Length, length);
CoverWallUtil.CopyCoverWallVertices(side, vertices.Data, sideVertices, staticGeometryData.Index, location);
vertices.Length += length;
m_coverWallLookup[key] = staticGeometryData;

if (!m_worldReload)
{
geometryVbo.Bind();
geometryVbo.UploadSubData(staticGeometryData.Index, length);
}

var vertices = vbo.Data;
vbo.Data.EnsureCapacity(vertices.Length + sideVertices.Length);
staticGeometryData = new(useGeometry, vertices.Length, length);
CoverWallUtil.CopyCoverWallVertices(side, vertices.Data, sideVertices, staticGeometryData.Index, location);
vertices.Length += length;
m_coverWallLookup[key] = staticGeometryData;
vbo.Bind();
vbo.UploadSubData(staticGeometryData.Index, length);
geometryVbo.Data.Length = Math.Max(geometryVbo.Data.Length, staticGeometryData.Index + length);
}
}

vbo.Data.Length = Math.Max(vbo.Data.Length, staticGeometryData.Index + length);
private static void EnsureCoverWallVboCapacity(in StaticGeometryData staticGeometryData, Span<DynamicVertex> sideVertices, StaticVertexBuffer<StaticVertex> geometryVbo)
{
// This generally shouldn't happen but vanilla sprite clipping emulation renders two-sided middle cover walls that may overflow the original calculation since textures can move/change.
if (geometryVbo.Data.Capacity < staticGeometryData.Index + sideVertices.Length)
{
geometryVbo.Data.EnsureCapacity(staticGeometryData.Index + sideVertices.Length);
geometryVbo.SetNotUploaded();
}
}

private void AddOrUpdateCoverFlatGeometry(Sector sector, SectorPlane plane, DynamicVertex[] vertices)
Expand Down
Loading