diff --git a/OpenRA.Game/Graphics/Viewport.cs b/OpenRA.Game/Graphics/Viewport.cs index dc137c5c6c..4e10821ef7 100644 --- a/OpenRA.Game/Graphics/Viewport.cs +++ b/OpenRA.Game/Graphics/Viewport.cs @@ -250,6 +250,9 @@ namespace OpenRA.Graphics else Zoom = Zoom.Clamp(minZoom, maxZoom); + var maxSize = (1f / (unlockMinZoom ? unlockedMinZoom : minZoom) * new float2(Game.Renderer.NativeResolution)); + Game.Renderer.SetMaximumViewportSize(new Size((int)maxSize.X, (int)maxSize.Y)); + foreach (var t in worldRenderer.World.WorldActor.TraitsImplementing()) t.ViewportZoomExtentsChanged(minZoom, maxZoom); } diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index a2bd3fd9c9..751f5fd412 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -50,8 +50,11 @@ namespace OpenRA Sprite screenSprite; IFrameBuffer worldBuffer; + Sheet worldSheet; Sprite worldSprite; + public Size WorldFrameBufferSize => worldSheet.Size; + SheetBuilder fontSheetBuilder; readonly IPlatform platform; @@ -59,7 +62,6 @@ namespace OpenRA Size lastBufferSize = new Size(-1, -1); - Size lastWorldBufferSize = new Size(-1, -1); Rectangle lastWorldViewport = Rectangle.Empty; ITexture currentPaletteTexture; IBatchRenderer currentBatchRenderer; @@ -178,14 +180,9 @@ namespace OpenRA } } - public void BeginWorld(Rectangle worldViewport) + public void SetMaximumViewportSize(Size size) { - if (renderType != RenderType.None) - throw new InvalidOperationException($"BeginWorld called with renderType = {renderType}, expected RenderType.None."); - - BeginFrame(); - - var worldBufferSize = worldViewport.Size.NextPowerOf2(); + var worldBufferSize = size.NextPowerOf2(); if (worldSprite == null || worldSprite.Sheet.Size != worldBufferSize) { worldBuffer?.Dispose(); @@ -195,24 +192,36 @@ namespace OpenRA // Pixel art scaling mode is a customized bilinear sampling worldBuffer.Texture.ScaleFilter = TextureScaleFilter.Linear; + worldSheet = new Sheet(SheetType.BGRA, worldBuffer.Texture); + + // Invalidate cached state to force a shader update + lastWorldViewport = Rectangle.Empty; + worldSprite = null; } + } + + public void BeginWorld(Rectangle worldViewport) + { + if (renderType != RenderType.None) + throw new InvalidOperationException($"BeginWorld called with renderType = {renderType}, expected RenderType.None."); + + BeginFrame(); + + if (worldSheet == null) + throw new InvalidOperationException($"BeginWorld called before SetMaximumViewportSize has been set."); if (worldSprite == null || worldViewport.Size != worldSprite.Bounds.Size) - { - var worldSheet = new Sheet(SheetType.BGRA, worldBuffer.Texture); worldSprite = new Sprite(worldSheet, new Rectangle(int2.Zero, worldViewport.Size), TextureChannel.RGBA); - } worldBuffer.Bind(); - if (worldBufferSize != lastWorldBufferSize || lastWorldViewport != worldViewport) + if (lastWorldViewport != worldViewport) { - var depthScale = worldBufferSize.Height / (worldBufferSize.Height + depthMargin); - WorldSpriteRenderer.SetViewportParams(worldBufferSize, depthScale, depthScale / 2, worldViewport.Location); - WorldModelRenderer.SetViewportParams(worldBufferSize, worldViewport.Location); + var depthScale = worldSheet.Size.Height / (worldSheet.Size.Height + depthMargin); + WorldSpriteRenderer.SetViewportParams(worldSheet.Size, depthScale, depthScale / 2, worldViewport.Location); + WorldModelRenderer.SetViewportParams(worldSheet.Size, worldViewport.Location); lastWorldViewport = worldViewport; - lastWorldBufferSize = worldBufferSize; } renderType = RenderType.World; diff --git a/OpenRA.Mods.Common/Widgets/Logic/PerfDebugLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/PerfDebugLogic.cs index 85fff281ec..171e3a0915 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/PerfDebugLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/PerfDebugLogic.cs @@ -10,6 +10,7 @@ #endregion using System.Diagnostics; +using OpenRA.Graphics; using OpenRA.Support; using OpenRA.Widgets; @@ -18,7 +19,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class PerfDebugLogic : ChromeLogic { [ObjectCreator.UseCtor] - public PerfDebugLogic(Widget widget) + public PerfDebugLogic(Widget widget, WorldRenderer worldRenderer) { var perfGraph = widget.Get("GRAPH_BG"); perfGraph.IsVisible = () => Game.Settings.Debug.PerfGraph; @@ -40,7 +41,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic fpsReferenceFrame = Game.RenderFrame; } - return $"FPS: {fps}\nTick {Game.LocalTick} @ {PerfHistory.Items["tick_time"].Average(Game.Settings.Debug.Samples):F1} ms\nRender {Game.RenderFrame} @ {PerfHistory.Items["render"].Average(Game.Settings.Debug.Samples):F1} ms\nBatches: {PerfHistory.Items["batches"].LastValue}"; + var wfbSize = Game.Renderer.WorldFrameBufferSize; + var viewportSize = worldRenderer.Viewport.Rectangle.Size; + return $"FPS: {fps}\nTick {Game.LocalTick} @ {PerfHistory.Items["tick_time"].Average(Game.Settings.Debug.Samples):F1} ms\n" + + $"Render {Game.RenderFrame} @ {PerfHistory.Items["render"].Average(Game.Settings.Debug.Samples):F1} ms\n" + + $"Batches: {PerfHistory.Items["batches"].LastValue}\n" + + $"Viewport Size: {viewportSize.Width} x {viewportSize.Height}\n" + + $"WFB Size: {wfbSize.Width} x {wfbSize.Height}"; }; } } diff --git a/mods/cnc/chrome/ingame.yaml b/mods/cnc/chrome/ingame.yaml index 030a2c4760..c4d071810c 100644 --- a/mods/cnc/chrome/ingame.yaml +++ b/mods/cnc/chrome/ingame.yaml @@ -53,7 +53,7 @@ Container@PERF_WIDGETS: Children: Label@PERF_TEXT: X: WINDOW_RIGHT - 200 - Y: WINDOW_BOTTOM - 70 + Y: WINDOW_BOTTOM - 90 Width: 170 Height: 40 Contrast: true