From c0dd3281c28361ffc81417d79cf968c0f07f3d0d Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 15 Sep 2026 06:47:40 -0400 Subject: [PATCH 1/3] clear SkyGeometry on reset. StaticCacheGeometryRenderer will readd them but when the property still exists it causes it to try to clear memory outside the bounds of the GPU. adds release guard to never try to upload outside of range as well --- Core/Render/OpenGL/Buffer/ArrayBufferObject.cs | 4 ++++ .../World/Geometry/Static/SkyGeometryManager.cs | 17 ++++++----------- Core/World/Geometry/Sides/Side.cs | 1 + RELEASENOTES.md | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Core/Render/OpenGL/Buffer/ArrayBufferObject.cs b/Core/Render/OpenGL/Buffer/ArrayBufferObject.cs index 6894a5b55..3c696b9d5 100644 --- a/Core/Render/OpenGL/Buffer/ArrayBufferObject.cs +++ b/Core/Render/OpenGL/Buffer/ArrayBufferObject.cs @@ -59,6 +59,10 @@ protected unsafe override bool BufferSubData(int index, int length) int size = BytesPerElement * length; Assert.Precondition(m_uploadedSize >= offset + size, "Offset and size are out of bounds for the GPU"); + // This shouldn't happen and should be handled upstream but never upload out of range for the GPU. + if (m_uploadedSize < offset + size) + return false; + GL.BufferSubData(Target, offset, size, ptr + (BytesPerElement * index)); } return true; diff --git a/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs b/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs index be69d54c8..12374eb39 100644 --- a/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs +++ b/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs @@ -1,10 +1,11 @@ -using System.Collections.Generic; -using Helion.Render.OpenGL.Buffer.Array.Vertex; +using Helion.Render.OpenGL.Buffer.Array.Vertex; using Helion.Render.OpenGL.Renderers.Legacy.World.Sky; using Helion.Render.OpenGL.Renderers.Legacy.World.Sky.Sphere; using Helion.World.Geometry.Sectors; using Helion.World.Geometry.Sides; using Helion.World.Geometry.Walls; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace Helion.Render.OpenGL.Renderers.Legacy.World.Geometry.Static; @@ -43,8 +44,7 @@ public static void AddSide(ISkyComponent sky, Side side, WallLocation wallLocati int index = sky.Vbo.Count; sky.Add(vertices, vertices.Length); - if (side.SkyGeometry == null) - side.SkyGeometry = new(); + side.SkyGeometry ??= new(); if (vertices == null) return; @@ -137,13 +137,8 @@ private static void ClearSkyGeometry(StaticSkyGeometryData? data) if (data == null) return; - for (int i = 0; i < data.Length; i++) - { - int index = data.Index + i; - data.Vbo.Data.Data[index].X = 0; - data.Vbo.Data.Data[index].Y = 0; - data.Vbo.Data.Data[index].Z = 0; - } + ref var reference = ref data.Vbo.Data.Data[data.Index]; + Unsafe.InitBlockUnaligned(ref Unsafe.As(ref reference), 0, (uint)(Marshal.SizeOf() * data.Length)); data.Vbo.Bind(); data.Vbo.UploadSubData(data.Index, data.Length); diff --git a/Core/World/Geometry/Sides/Side.cs b/Core/World/Geometry/Sides/Side.cs index c4ddb7e98..44c936292 100644 --- a/Core/World/Geometry/Sides/Side.cs +++ b/Core/World/Geometry/Sides/Side.cs @@ -125,6 +125,7 @@ public void Reset() MiddleInvalidatedCount = default; LowerInvalidatedCount = default; AlphaInvalidatedCount = default; + SkyGeometry = default; Upper.Reset(); Middle.Reset(); diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 19bcbb6c1..a73e0ab03 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -30,6 +30,7 @@ - Fix status bar weapon slot condition to correctly check against switched weapon instead of the weapon that's actively being switched to. - Fix status bar uses ammo condition. - Fix BufferSubData call that could write out of bounds on GPU resulting in corrupted/missing walls. +- Fix sky geometry holding stale references on map reloads. - Fix rendering issue with lines when changing transfer heights views. - Fix width, speed, and mass properties to default to zero for dehacked instead of using default decorate values. From f592dd0e590b1df83c341d8524f22e70e17dbf2b Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 15 Sep 2026 06:52:30 -0400 Subject: [PATCH 2/3] fix typo --- Core/Util/Configs/Components/ConfigRender.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Util/Configs/Components/ConfigRender.cs b/Core/Util/Configs/Components/ConfigRender.cs index c46f6f130..7f8e17c23 100644 --- a/Core/Util/Configs/Components/ConfigRender.cs +++ b/Core/Util/Configs/Components/ConfigRender.cs @@ -88,7 +88,7 @@ public class ConfigRenderHealthBar : ConfigElement public class ConfigRender : ConfigElement { - [ConfigInfo("Changes the render mode. Adaptive can be very beneficial on itegrated GPUs.")] + [ConfigInfo("Changes the render mode. Adaptive can be very beneficial on integrated GPUs.")] [OptionMenu(OptionSectionType.Render, "Mode")] public readonly ConfigValue Mode = new(AdaptiveRenderMode.Static); public readonly ConfigRenderAdaptive Adaptive = new(); From 7cf3d0d74d60b635d8d5d2a0ead491a83812c30f Mon Sep 17 00:00:00 2001 From: Nick <42744211+nstlaurent@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:31:08 -0400 Subject: [PATCH 3/3] correct size of type (#1789) --- .../Legacy/World/Geometry/Static/SkyGeometryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs b/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs index 12374eb39..ee5f9e244 100644 --- a/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs +++ b/Core/Render/OpenGL/Renderers/Legacy/World/Geometry/Static/SkyGeometryManager.cs @@ -138,7 +138,7 @@ private static void ClearSkyGeometry(StaticSkyGeometryData? data) return; ref var reference = ref data.Vbo.Data.Data[data.Index]; - Unsafe.InitBlockUnaligned(ref Unsafe.As(ref reference), 0, (uint)(Marshal.SizeOf() * data.Length)); + Unsafe.InitBlockUnaligned(ref Unsafe.As(ref reference), 0, (uint)(Marshal.SizeOf() * data.Length)); data.Vbo.Bind(); data.Vbo.UploadSubData(data.Index, data.Length);