From 18a59525b9d0cd08c7c2278398fb9ac4b0a2eeb4 Mon Sep 17 00:00:00 2001 From: jrhodnik Date: Fri, 24 May 2019 21:10:01 -0400 Subject: [PATCH] Fixed flickering. Updating texture pixels rather than swapping them out. Much more effecient. --- VDash/Overlay/WindowOverlay.cs | 117 +++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/VDash/Overlay/WindowOverlay.cs b/VDash/Overlay/WindowOverlay.cs index 2a269f6..ec09f2b 100644 --- a/VDash/Overlay/WindowOverlay.cs +++ b/VDash/Overlay/WindowOverlay.cs @@ -1,4 +1,5 @@ -using SharpDX.Direct3D11; +using SharpDX; +using SharpDX.Direct3D11; using SharpDX.DXGI; using System; using System.Drawing; @@ -104,6 +105,16 @@ namespace VDash.Overlay var adapter = factory.GetAdapter1(0); //Get device from adapter var device = new SharpDX.Direct3D11.Device(adapter); + + int lastWidth = 0; + int lastHeight = 0; + + + // Create Staging texture CPU-accessible + //Actual screen texture. + //var screenTexture = new Texture2D(device, textureDesc); + Texture2D screenTexture = null; + DataStream stream = null; #endregion //For FPS counter. @@ -191,6 +202,8 @@ namespace VDash.Overlay int width = rect.right - rect.left; int height = rect.bottom - rect.top; + + using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb)) { using (Graphics graphics = Graphics.FromImage(bmp)) @@ -199,24 +212,87 @@ namespace VDash.Overlay var data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - //Render using graphics card, in DirectX context. - // Create Staging texture CPU-accessible - var textureDesc = new Texture2DDescription - { - CpuAccessFlags = CpuAccessFlags.Read, - BindFlags = BindFlags.None, - Format = Format.B8G8R8A8_UNorm, - Width = width, - Height = height, - OptionFlags = ResourceOptionFlags.None, - MipLevels = 1, - ArraySize = 1, - SampleDescription = { Count = 1, Quality = 0 }, - Usage = ResourceUsage.Staging - }; - using (var screenTexture = new Texture2D(device, textureDesc, new SharpDX.DataRectangle(data.Scan0, data.Stride))) + if (screenTexture == null || (lastWidth != data.Width || lastHeight != data.Height)) { + lastWidth = data.Width; + lastHeight = data.Height; + + if (screenTexture != null) + { + screenTexture.Dispose(); + + //Dispose not freeing screenTexture: https://gamedev.stackexchange.com/questions/93311/freeing-texture-memory-in-sharpdx-what-am-i-missing + device.ImmediateContext.ClearState(); + device.ImmediateContext.Flush(); + } + + var textureDesc = new Texture2DDescription + { + CpuAccessFlags = CpuAccessFlags.Write, + BindFlags = BindFlags.ShaderResource, + Format = Format.B8G8R8A8_UNorm, + //Format = Format.B8G8R8A8_UNorm_SRgb, + Width = data.Width, + Height = data.Height, + OptionFlags = ResourceOptionFlags.None, + MipLevels = 1, + ArraySize = 1, + SampleDescription = { Count = 1, Quality = 0 }, + Usage = ResourceUsage.Dynamic + }; + screenTexture = new Texture2D(device, textureDesc); + stream = new DataStream(4 * width * height, true, true); + + Console.WriteLine("Updated!"); + + + } + //Render using graphics card, in DirectX context. + + //using () + { + + var screenView = new ShaderResourceView(device, screenTexture); + device.ImmediateContext.PixelShader.SetShaderResource(0, screenView); + + var dr = new SharpDX.DataRectangle(data.Scan0, data.Stride); + + DataBox databox = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.WriteDiscard, + SharpDX.Direct3D11.MapFlags.None, out stream); + + + + if (!databox.IsEmpty) + { + int count = 4 * data.Width * data.Height; + + //Stride compensation. Sometimes the BMP and DX texture strides are different. This fixes it. + if (databox.RowPitch == data.Stride) + { + stream.Write(data.Scan0, 0, count); + } + //Truncate the extra BMP bytes. + else if (databox.RowPitch < data.Stride) + { + for (int i = 0; i < data.Height; i++) + { + stream.Write(data.Scan0, (data.Stride * i), databox.RowPitch); + } + } + //Add some junk on empty bytes on the end to make everyone happy. + else if(databox.RowPitch > data.Stride) + { + int difference = databox.RowPitch - data.Stride; + byte[] junk = new byte[difference]; + for (int i = 0; i < data.Height; i++) + { + stream.Write(data.Scan0, (data.Stride * i), data.Stride); + stream.Write(junk, 0, difference); + } + } + } + var texture = new Texture_t(); texture.handle = screenTexture.NativePointer; texture.eType = ETextureType.DirectX; @@ -227,13 +303,14 @@ namespace VDash.Overlay Console.WriteLine($"Error rendering: {result}"); } + device.ImmediateContext.UnmapSubresource(screenTexture, 0); + + + frames++; bmp.UnlockBits(data); } - //Dispose not freeing screenTexture: https://gamedev.stackexchange.com/questions/93311/freeing-texture-memory-in-sharpdx-what-am-i-missing - device.ImmediateContext.ClearState(); - device.ImmediateContext.Flush(); } } }