2014-11-29 10 views
6

में इंटरफेस मेरे पास सीआर ++ में लिखा गया मेरा डायरेक्टएक्स 11 इंजन है, सीएलआर के साथ सी ++ में एक रैपर, और सी # में एक इंटरफ़ेस है।सी ++ में डायरेक्टएक्स 11 इंजन और सी #

1) मैं इस संरचना में बाधा कहां से उत्सुक हूं, और मैं सोच रहा हूं कि WinForms नियंत्रण में DirectX11 प्रतिपादन को होस्ट करने के लिए एक और अधिक प्रभावी तरीका है या नहीं।

2) क्या WinForms नियंत्रण के मालिक के अलावा किसी अन्य धागे को प्रस्तुत करने का कोई तरीका है? मुझे शक है लेकिन लगा कि मैं पूछूंगा।

3) क्या प्रत्येक फ्रेम पर रैपर परत के बिना बिना कई फ्रेम प्रस्तुत करने का कोई तरीका है लेकिन एप्लिकेशन को उत्तरदायी रखें?

मैंने इस सेटअप की तुलना स्लिम डीएक्स से की है और वास्तव में स्क्रीन को साफ़ करने और किसी भी अन्य एपीआई कॉल नहीं करते समय थोड़ा धीमी एफपीएस प्राप्त कर रहा हूं। स्लिम डीएक्स ~ 3000 एफपीएस, मेरा इंजन ~ 2000 एफपीएस। यह एक बड़ा सौदा नहीं है, लेकिन मैं सोच रहा हूं कि यह 33% अंतर कहाँ से आ रहा है क्योंकि 20 एफपीएस की तुलना में 30 एफपीएस की तुलना में शायद यह अंतर आएगा।

मैं वर्तमान सेटअप के माध्यम से चलूंगा और जितना अधिक वर्णन करूंगा हाँ मैं। मुझे यकीन है कि लोग अधिक जानकारी के लिए पूछेंगे और मैं आवश्यकतानुसार अपडेट करूंगा।

मेरा WinForms GraphicsPanel Control नीचे है। यह सिस्टम संदेशों को रैपर परत में पास करता है।

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 नियंत्रण से संदेश पारित करने के लिए इस समारोह की है।

void EngineWrapper::ProcessWindowMessage(int msg, System::IntPtr wParam, System::IntPtr lParam) 
{ 
    m_Engine->ProcessWindowMessage(msg, (void*)wParam, (void*)lParam); 
} 

अंत में, मूल निवासी सी ++ इंजन प्रक्रियाओं जैसे संदेशों:

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); 
    } 
} 
+0

इस विषय पर 1000 पेज पुस्तकें हैं, मुझे नहीं पता कि मैं कुछ पैराग्राफ में उपयोगी (या सही) उत्तर लिख सकता हूं या नहीं। – BlamKiwi

+0

कोई अंतर्दृष्टि या आलोचना की सराहना की जाती है। –

+0

मैं सप्ताहांत में कुछ एक साथ रखूंगा। – BlamKiwi

उत्तर

4

1) मैं कहाँ टोंटी इस संरचना में है के बारे में उत्सुक हूँ, और मैं अगर सोच रहा हूँ WinForms नियंत्रण में DirectX11 प्रतिपादन की मेजबानी करने के लिए एक और अधिक प्रभावी तरीका है।

SlimDX की वजह से अंतर की अनदेखी सी में लागू किया जा रहा ++/CLI (जो नगण्य होना चाहिए), the SlimDX implementation की तुलना में फर्क सिर्फ इतना है अपने कोड में मैं देख रहा हूँ यह है कि आप संदेश प्रसंस्करण के साथ अपने इंजन परेशान कर रहे हैं:

protected override void WndProc(ref Message m) 
{ 
    base.WndProc(ref m); 
    PassMessage(m); 
} 

मैं बल्कि सरल बनाना चाहता हूं और संदेश इंजन को अपने इंजन से दूर रखना चाहता हूं। अपने WndProc ओवरराइड में संदेश संभाल और आह्वान जो कुछ आपरेशनों आप Engine पर की जरूरत है और DrawFrame सीधे कॉल जब भी निष्क्रिय (जैसे Resize, MouseMove, MouseClick, या इनपुट प्रसंस्करण के अन्य प्रकार।):

private void OnApplicationIdle(object sender, EventArgs e) 
{ 
    while (AppStillIdle) 
     if (Engine != null) 
      Engine.DrawFrame(); 
} 

मैं उम्मीद नहीं होता यह ~ 33% प्रदर्शन अंतर के लिए जिम्मेदार है लेकिन यह देखने में लायक हो सकता है।

2) क्या WinForms नियंत्रण के मालिक के अलावा किसी अन्य धागे को प्रस्तुत करने का कोई तरीका है? मुझे शक है लेकिन लगा कि मैं पूछूंगा।

हां, आप ऑफ-स्क्रीन सतहों का उपयोग कर सकते हैं। हालांकि, फिर समस्या यह हो जाती है कि अपनी विंडो सामग्री को कैसे अपडेट किया जाए। उदाहरण के लिए, आप एक चित्र दर्शक का उपयोग कर सकते हैं और ऑफ-स्क्रीन सतह से प्राप्त छवि सेट कर सकते हैं लेकिन इससे एक खराब प्रदर्शन होगा।

3) क्या प्रत्येक फ्रेम पर रैपर परत के बिना बिना कई फ्रेम प्रस्तुत करने का कोई तरीका है लेकिन एप्लिकेशन को उत्तरदायी रखें?

Given the approach you are using, फ़्रेम आपके एप्लिकेशन निष्क्रिय ईवेंट हैंडलर से ऑन-डिमांड प्रदान किए जाते हैं, इसलिए नहीं। आप पिछले बिंदु में समझाए गए ऑफ-स्क्रीन का उपयोग करके ऐसा कर सकते हैं।

+1

यह सुनिश्चित करने के लिए कि किसी अन्य फ्रेम से पहले संदेशों को हमेशा संसाधित किया जाता है, यह सुनिश्चित करने के लिए संदेश प्रसंस्करण को आपके गेम लूप का एक एकल थ्रेड गेम में भाग लेना आम बात है। यह Win32 और Windows से इनपुट विलंबता को कम करने में सहायता करता है यह पता लगाने पर कि आपका एप्लिकेशन वास्तव में क्रैश हो गया है या नहीं। – BlamKiwi