我有一个用C++编写的DirectX11引擎,一个带有CLR的C++包装器和一个用C#编写的接口。
1)我想知道这个结构的瓶颈在哪里,是否有更有效的方法让我在WinForms控件中托管DirectX11渲染。
2)除了WinForms控件的所有者线程之外,是否有其他线程可以进行渲染?我怀疑没有,但还是想问一下。
3)是否有一种方法可以在不在每一帧都通过包装层进行渲染的情况下渲染多个帧,同时保持应用程序的响应性?
我已将此设置与SlimDX进行比较,仅清除屏幕而不进行任何其他API调用时,实际上会获得稍微较慢的FPS。 SlimDX约为3000 FPS,我的引擎约为2000 FPS。虽然这并不是什么大问题,但我想知道这33%的差异来自哪里,因为当将20 fps与30 fps进行比较时,它可能会产生影响。
我将介绍当前的设置并尽可能地描述。我相信在此过程中人们会要求更多的信息,我会根据需要进行更新。
我的WinForms GraphicsPanel控件如下所示。它将系统消息传递给包装层。
在引擎封装器中,我有这个函数来将WinForms控件的消息传递到本地C++层。
最后,本地C++引擎会按如下方式处理消息:
1)我想知道这个结构的瓶颈在哪里,是否有更有效的方法让我在WinForms控件中托管DirectX11渲染。
2)除了WinForms控件的所有者线程之外,是否有其他线程可以进行渲染?我怀疑没有,但还是想问一下。
3)是否有一种方法可以在不在每一帧都通过包装层进行渲染的情况下渲染多个帧,同时保持应用程序的响应性?
我已将此设置与SlimDX进行比较,仅清除屏幕而不进行任何其他API调用时,实际上会获得稍微较慢的FPS。 SlimDX约为3000 FPS,我的引擎约为2000 FPS。虽然这并不是什么大问题,但我想知道这33%的差异来自哪里,因为当将20 fps与30 fps进行比较时,它可能会产生影响。
我将介绍当前的设置并尽可能地描述。我相信在此过程中人们会要求更多的信息,我会根据需要进行更新。
我的WinForms GraphicsPanel控件如下所示。它将系统消息传递给包装层。
public class GraphicsPanel : Control
{
EngineWrapper Engine;
public GraphicsPanel()
{
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.UserMouse, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.TabStop = true;
}
public void SetEngine(EngineWrapper Engine)
{
this.Engine = Engine;
Application.Idle += OnApplicationIdle;
}
~GraphicsPanel()
{
System.Windows.Forms.Application.Idle -= OnApplicationIdle;
}
void PassMessage(Message m)
{
Engine.ProcessWindowMessage(m.Msg, m.WParam, m.LParam);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
PassMessage(m);
}
private void OnApplicationIdle(object sender, EventArgs e)
{
while (AppStillIdle)
if (Engine != null)
Engine.ProcessWindowMessage(0, IntPtr.Zero, IntPtr.Zero);
}
public bool AppStillIdle
{
get
{
NativeMethods.PeekMsg msg;
return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
}
}
internal class NativeMethods
{
private NativeMethods() { }
[StructLayout(LayoutKind.Sequential)]
public struct PeekMsg
{
public IntPtr hWnd;
public Message msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(out PeekMsg msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
}
}
在引擎封装器中,我有这个函数来将WinForms控件的消息传递到本地C++层。
void EngineWrapper::ProcessWindowMessage(int msg, System::IntPtr wParam, System::IntPtr lParam)
{
m_Engine->ProcessWindowMessage(msg, (void*)wParam, (void*)lParam);
}
最后,本地C++引擎会按如下方式处理消息:
void Input::ProcessWindowMessage(int msg, void* wParam, void* lParam)
{
if (msg == 0 || msg == WM_PAINT)
{
DrawFrame();
}
else if (msg == WM_SIZING || msg == WM_SIZE)
{
DoResize();
DrawFrame();
}
else if (msg >= WM_MOUSEFIRST && msg <= WM_MOUSEWHEEL)
{
ProcessMouseMessage(msg, wParam, lParam);
}
}