i am making an app that overlays other d3d games,
the app is working perfectly except it has a huge performance impact on the cpu
taking 21.4 % of the cpu when rendering only a single line !
i am using slimdx library on c# and here is my full code
OverLay.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SlimDX.Direct3D11;
using SlimDX.Windows;
using System.Runtime.InteropServices;
using System.Security;
using SlimDX;
using SlimDX.DXGI;
using Device = SlimDX.Direct3D9.Device;
using Resource = SlimDX.Direct3D9.Resource;
using System.Threading;
using D3D = SlimDX.Direct3D9;
namespace OverlayForm
{
public partial class OverLay : RenderForm
{
RenderForm form;
Device device;
// D3D.Sprite sprite;
public OverLay()
{
InitializeComponent();
Paint += OverLay_Paint;
FormBorderStyle = FormBorderStyle.None;
ShowIcon = false;
ShowInTaskbar = false;
TopMost = true;
WindowState = FormWindowState.Maximized;
//Make the window's border completely transparant
//SetWindowLong(Handle , GWL_EXSTYLE , (IntPtr)(GetWindowLong(Handle , GWL_EXSTYLE) ^ WS_EX_LAYERED ^ WS_EX_TRANSPARENT));
SetWindowLong(Handle , GWL_EXSTYLE , (IntPtr)(GetWindowLong(Handle , GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));
//Set the Alpha on the Whole Window to 255 (solid)
SetLayeredWindowAttributes(Handle , 0 , 255 , LWA_ALPHA);
form = this;
form.FormClosing += Form_FormClosing;
//Init DirectX
//This initializes the DirectX device. It needs to be done once.
//The alpha channel in the backbuffer is critical.
D3D.PresentParameters presentParameters = new D3D.PresentParameters();
presentParameters.Windowed = true;
presentParameters.SwapEffect = D3D.SwapEffect.Discard;
presentParameters.BackBufferFormat = D3D.Format.A8R8G8B8;
device = new Device(new D3D.Direct3D() , 0 , D3D.DeviceType.Hardware , Handle ,
D3D.CreateFlags.HardwareVertexProcessing , presentParameters);
//sprite = new D3D.Sprite(device);
font = new D3D.Font(device , new Font("Arial" , 9 , FontStyle.Regular));
line = new D3D.Line(this.device);
MessagePump.Run(form , new MainLoop(dxThread));
}
private void Form_FormClosing(object sender , FormClosingEventArgs e)
{
device.Dispose();
}
int centerx = Screen.PrimaryScreen.WorkingArea.Width / 2;
int centery = Screen.PrimaryScreen.WorkingArea.Height / 2;
private void OverLay_Paint(object sender , PaintEventArgs e)
{
//Create a margin (the whole form)
marg.Left = 0;
marg.Top = 0;
marg.Right = Width;
marg.Bottom = Height;
//Expand the Aero Glass Effect Border to the WHOLE form.
// since we have already had the border invisible we now
// have a completely invisible window - apart from the DirectX
// renders NOT in black.
DwmExtendFrameIntoClientArea(Handle , ref marg);
}
private static D3D.Font font;
private static D3D.Line line;
private void dxThread()
{
form.TopMost = true;
device.SetRenderState(D3D.RenderState.ZEnable , false);
device.SetRenderState(D3D.RenderState.Lighting , false);
device.SetRenderState(D3D.RenderState.CullMode , D3D.Cull.None);
device.SetTransform(D3D.TransformState.Projection , Matrix.OrthoOffCenterLH(0 , Width , Height , 0 , 0 , 1));
device.BeginScene();
//DrawFilledBox(0 , 0 , 100 , 100 , Color.White);
//font.DrawString( null, "Swag" , 10, 10 , new Color4(Color.White));
//DrawBox(0 , 0 , 10 , 10 , 1 , Color.Green);
DrawLine(0 , 0 , Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Height , 2 , Color.Pink);
device.EndScene();
device.Present();
}
public static void DrawFilledBox(float x , float y , float w , float h , Color Color)
{
Vector2[] vLine = new Vector2[2];
line.GLLines = true;
line.Antialias = false;
line.Width = w;
vLine[0].X = x + w / 2;
vLine[0].Y = y;
vLine[1].X = x + w / 2;
vLine[1].Y = y + h;
line.Begin();
line.Draw(vLine , new Color4(Color));
line.End();
}
public static void DrawLine(float x1 , float y1 , float x2 , float y2 , float w , Color Color)
{
Vector2[] vLine = new Vector2[2] { new Vector2(x1 , y1) , new Vector2(x2 , y2) };
line.GLLines = true;
line.Antialias = false;
line.Width = w;
line.Begin();
line.Draw(vLine , new Color4(Color));
line.End();
}
public static void DrawBox(float x , float y , float w , float h , float px , System.Drawing.Color Color)
{
DrawFilledBox(x , y + h , w , px , Color);
DrawFilledBox(x - px , y , px , h , Color);
DrawFilledBox(x , y - px , w , px , Color);
DrawFilledBox(x + w , y , px , h , Color);
}
#region Extras
private Margins marg;
//this is used to specify the boundaries of the transparent area
internal struct Margins
{
public int Left, Right, Top, Bottom;
}
[DllImport("user32.dll" , SetLastError = true)]
private static extern UInt32 GetWindowLong(IntPtr hWnd , int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd , int nIndex , IntPtr dwNewLong);
[DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(IntPtr hwnd , uint crKey , byte bAlpha , uint dwFlags);
public const int GWL_EXSTYLE = -20;
public const int WS_EX_LAYERED = 0x80000;
public const int WS_EX_TRANSPARENT = 0x20;
public const int LWA_ALPHA = 0x2;
public const int LWA_COLORKEY = 0x1;
[DllImport("dwmapi.dll")]
static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd , ref Margins pMargins);
#endregion
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OverlayForm
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
using (OverLay x = new OverLay())
{
}
}
}
}
Please note :
i already saw this : Very high CPU usage directx 9
but i am using MessagePump.Run
and don't know how to apply the answer.