delphi - क्या TDirect2DCanvas धीमा है या क्या मैं कुछ गलत कर रहा हूं?




delphi-2010 gdi (3)

जीडीआई को बदलने के विकल्पों की तलाश करते समय, मैं विंडोज 7 में डेल्फी के 2010 टीडायरेक्ट 2 डीकैनवास प्रदर्शन का परीक्षण करने की कोशिश कर रहा था।

मैंने डायरेक्ट 2 डी का उपयोग करके एक विशाल पॉलीलाइन ड्राइंग करके इसका परीक्षण किया और परिणाम जीडीआई का उपयोग करके एक ही परीक्षण चलाए गए राशि से 500 गुना कम डेटा के साथ भी बेतुका धीमा था (और मैंने जीडीआई में बैकबफर के रूप में बिटमैप का भी उपयोग नहीं किया था, मैं सिर्फ फॉर्म कैनवास के लिए सीधे आकर्षित किया)।

तो मुझे लगता है कि या तो:
ए) प्रत्यक्ष 2 डी जीडीआई से धीमी है;
बी) TDirect2DCanvas धीमा है;
सी) मैं कुछ गलत कर रहा हूँ
और उम्मीद है कि यह सी है)।

मैंने लिखा परीक्षण कोड है:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Direct2D, D2D1;

type
  TForm2 = class(TForm)
  private
    { Private declarations }
    FD2DCanvas: TDirect2DCanvas;
    FData: array[0..50000] of TPoint;
  public
    procedure CreateWnd; override;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;


    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses utils;

{$R *.dfm}

procedure TForm2.CreateWnd;
var
  i: Integer;
begin
  inherited;
  FD2DCanvas := TDirect2DCanvas.Create(Handle);

  for i := 0 to High(FData) do begin
    FData[i].X := Random(Self.ClientWidth  div 2);
    FData[i].Y := Random(Self.ClientHeight);
  end;
end;

procedure TForm2.WMPaint(var Message: TWMPaint);
var
  PaintStruct: TPaintStruct;
begin
  BeginPaint(Handle, PaintStruct);
  try
    FD2DCanvas.BeginDraw;

    try
      FD2DCanvas.Polyline(FData);
    finally
      FD2DCanvas.EndDraw;
    end;

  finally
    EndPaint(Handle, PaintStruct);
  end;

end;

procedure TForm2.WMSize(var Message: TWMSize);
begin
  if Assigned(FD2DCanvas) then begin
    ID2D1HwndRenderTarget(FD2DCanvas.RenderTarget).Resize(D2D1SizeU(ClientWidth, ClientHeight));
  end;
end;

end.

इसके अलावा, मैं वास्तव में वास्तविक कोड में लंबी पॉलिलाइन को आकर्षित करने के लिए तैयार हूं, एक प्रणाली के रूप में मैं ~ 2500 अंक पॉलीलाइनों (उनमें से कम से कम 10 के) को आकर्षित करने की आवश्यकता पर काम कर रहा हूं।

अपडेट किया गया (2010-11-06)

मुझे पहले पता चला है कि डायरेक्ट 2 डी पॉलिलाइन की तरह प्रतीत नहीं होता है, यदि आप बहुत सी लाइनों (2 पॉइंट पॉलीलाइन) का उपयोग करते हैं तो यह तेजी से आकर्षित होता है।

क्रिस बेन्सन के लिए धन्यवाद, मैंने पाया कि एंटी-एलियासिंग का उपयोग करते समय धीमी गति से बड़ी पॉलिलाइन के साथ था। तो मैंने एंटी-एलियासिंग को अक्षम कर दिया क्योंकि क्रिस ने सुझाव दिया था और 50k लाइनों को चित्रित करने के लिए प्रदर्शन ~ 6000ms से ~ 3500ms तक चला गया था।

चीजें अभी भी सुधरी जा सकती हैं क्योंकि डायरेक्ट 2 डी एंटी-एलाइजिंग का उपयोग करते समय अच्छी पॉलिलाइन को संभाल नहीं पाती है। एंटी-एलाइजिंग अक्षम होने के साथ यह सिर्फ विपरीत है।

अब 50k लाइनों के डायरेक्ट 2 डी के साथ ड्राइंग के लिए समय, अगर मैं एंटी-एलियासिंग के बिना बड़ी पॉलीलाइन खींचता हूं, तो ~ 50ms है। अच्छा, आह!

बात यह है कि यदि मैं बिटमैप पर आकर्षित करता हूं और इसे पूरा करने के बाद जीडीआई डायरेक्ट 2 डी से अभी भी तेज़ है, तो मैं परिणाम को वापस फॉर्मेट करता हूं, यह ~ 35ms पर और उसी ग्राफिक्स गुणवत्ता के साथ चित्रित करता है। और, डायरेक्ट 2 डी पहले से ही EndDraw() का उपयोग कर रहा है (यह केवल तब EndDraw() है जब EndDraw() कहा जाता है)।

तो, क्या इसे किसी भी तरह से डायरेक्ट 2 डी के लायक गति के उपयोग में सुधार करने के लिए बेहतर किया जा सकता है?

अद्यतन कोड यहां दिया गया है:

type
  TArray = array[0..1] of TPoint;
  PArray = ^TArray;

procedure TForm2.WMPaint(var Message: TWMPaint);
var
  PaintStruct: TPaintStruct;
begin
  FD2DCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  BeginPaint(Handle, PaintStruct);
  try
    FD2DCanvas.BeginDraw;
    try
      FD2DCanvas.Pen.Color := clRed;
      FD2DCanvas.Polyline(FData);
    finally
      FD2DCanvas.EndDraw;
    end;   
  finally
    EndPaint(Handle, PaintStruct);
  end;
end;

वैसे भी, अगर मैं पहले से ही ज्यामिति बनाने के क्रिस के सुझाव का उपयोग करता हूं तो गति जीडीआई के समान गति के बारे में है, लेकिन फिर भी तेज़ नहीं है।

मेरा कंप्यूटर सामान्य रूप से Direct3D और OpenGL ऐप्स चला रहा है और यहां dxDiag आउटपुट है: http://mydxdiag.pastebin.com/mfagLWnZ

मुझे खुशी होगी अगर कोई मुझे समझा सकता है कि यह धीमा क्यों है। नमूना कोड बहुत सराहना की है।


डायरेक्ट 2 डी ड्राइवर और हार्डवेयर कार्यान्वयन पर निर्भर करता है, इसलिए आप जिस हार्डवेयर और ड्राइवर पर चल रहे हैं उसके आधार पर प्रदर्शन विषमताएं हैं (3 डी प्रतिपादन इंजन के रूप में मुद्दों के समान बैग)।

उदाहरण के लिए प्रतिपादन लाइनों के मुद्दे पर, आपको कुछ (छिपे हुए) अंतर्निहित हार्डवेयर बफर मुद्दों का सामना करना पड़ेगा: किसी दिए गए हार्डवेयर + ड्राइवर पर, पॉलीलाइन ड्राइंग करते समय, अंतर्निहित डेटासाइज एक निश्चित दहलीज से नीचे है, तो प्रदर्शन उच्च हो सकता है , पूर्ण हार्डवेयर त्वरण के साथ। उस दहलीज के ऊपर, आप आंशिक रूप से सॉफ़्टवेयर या अप्रत्याशित पथ पर वापस आ सकते हैं, और प्रदर्शन कम हो जाएगा। थ्रेसहोल्ड हार्डवेयर, ड्राइवर और ब्रश / ड्राइंग विकल्पों पर निर्भर करेगा, वहां हो सकता है या नहीं।

ये वही समस्याएं हैं जैसे ओपनजीएल या नियमित डायरेक्टएक्स के माध्यम से 2 डी या 3 डी प्रतिपादन करते समय, यदि आप अच्छी तरह से पतले प्रतिपादन पथों से बाहर भटक जाते हैं, तो चीजें इतनी गुलाबी नहीं होती हैं।

जहां तक ​​गैर-एंटीअलाइज्ड ग्राफिक्स को प्रस्तुत किया जाता है, मेरी सलाह जीडीआई के साथ रहना होगा, कार्यान्वयन व्यापक हार्डवेयर समर्थन के साथ ठोस हैं।

एंटीअलाइज्ड ग्राफिक्स के लिए, जीडीआई +, ग्राफिक्स 32, एजीजी, और बड़े पैमाने पर, सॉफ्टवेयर-केवल समाधान बेहतर आईएमई होते हैं जब भी आपके पास अंत उपयोगकर्ता हार्डवेयर पर कोई नियंत्रण नहीं होता है। अन्यथा, ग्राहक सहायता मुद्दों के लिए खुद को तैयार करें।


तुलना में जीडीआई + गति के बारे में क्या?

हमने एक मुक्त / मुक्त स्रोत इकाई लिखी, जीडीआई + इंजन का उपयोग कर किसी भी वीसीएल टीकैनवास सामग्री (टीएमटाफाइल का उपयोग करके) प्रस्तुत करने में सक्षम।

व्यावहारिक रूप से, प्रदर्शन बहुत अच्छा है, और एंटी-अलियाइजिंग चालू थी ... हम इसे कई परियोजनाओं में उपयोग करते हैं, नियमित घटकों की सामग्री को बिटमैप में चित्रित करते हैं, फिर स्क्रीन पर फ़ॉर्म सामग्री को चित्रित करने के लिए इस बिटमैप का उपयोग करते हैं (इससे किसी भी झिलमिलाहट की समस्या से बचेंगी )। और एंटी-एलाइजिंग के साथ, मार्केटिंग लोग परिणाम के बारे में खुश थे, और अन्य प्रोग्रामर (सी # या डब्ल्यूपीएफ का उपयोग करके) सोच रहे थे कि यह कैसे काम कर रहा था: ड्राइंग बहुत तेज है और एप्लिकेशन प्रतिक्रियाशील हैं (जैसे अच्छी तरह से निर्मित डेल्फी ऐप्स), बहुत उपयोग करें छोटी याददाश्त, और स्क्रीन पर परिणाम आधुनिक दिखता है (विशेष रूप से यदि आप कैलिब्ररी या ऐसे फोंट का उपयोग करते हैं जो आपके सिस्टम पर उपलब्ध हैं)।

http://synopse.info/forum/viewtopic.php?id=10 देखें

यह डेल्फी के किसी भी संस्करण (डेल्फी 6 से डेल्फी एक्सई तक) के साथ काम करेगा, और विंडोज़ (एक्सपी, विस्टा, सेवन - पिछले ओएस के साथ मानक gdiplus.dll को तैनात करने की आवश्यकता) के किसी भी संस्करण पर काम करेगा।

हमारी इकाई जीडीआई के लिए जीडीआई + एक्सपी पर रूपांतरण के लिए पास्कल कोड का उपयोग करती है, और Vista, Seven के तहत मूल माइक्रोसॉफ्ट छिपा एपीआई या पीसी पर Office 2003/2007 स्थापित है।


समस्या एंटीअलाइजिंग चालू है। एंटीअलाइजिंग अक्षम करें और डायरेक्ट 2 डी का प्रदर्शन जीडीआई की तुलना में बराबर या तेज होगा। TDirect2DCanvas के निर्माण के बाद ऐसा करने के लिए, यह कॉल करें:


  FD2DCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);

TDirect2DCanvas इंटरफ़ेस संगत है जहां टीसीएनवास के साथ संभव है ताकि यह टीसीएनवास के साथ प्रतिस्थापन में गिरावट हो, इसलिए कुछ ड्राइंग दिनचर्या थोड़ी अक्षम हैं। उदाहरण के लिए, पॉलीलाइन प्रत्येक बार एक ज्यामिति बनाता है जिसे इसे बुलाया जाता है और इसे फेंकता है। ज्यामिति को चारों ओर रखते हुए प्रदर्शन को बढ़ाने के लिए।

TDirect2DCanvas.Polyline के लिए कार्यान्वयन पर नज़र डालें और इस तरह के कुछ के लिए अपने आवेदन में बाहर निकलें:


procedure TForm2.CreateWnd;
var
  i: Integer;
  HR: HRESULT;
  Sink: ID2D1GeometrySink;
begin
...
  D2DFactory.CreatePathGeometry(FGeometry);
  HR := FGeometry.Open(Sink);
  try
    Sink.BeginFigure(D2D1PointF(FData[0].X + 0.5, FData[0].Y + 0.5), 
      D2D1_FIGURE_BEGIN_HOLLOW);
    try
      for I := Low(FData) + 1 to High(FData) - 1 do
        Sink.AddLine(D2D1PointF(FData[I].X + 0.5, FData[I].Y + 0.5));
    finally
      Sink.EndFigure(D2D1_FIGURE_END_OPEN);
    end;
  finally
    hr := Sink.Close;
  end;

और फिर इसे इस तरह आकर्षित करें:


procedure TForm2.WMPaint(var Message: TWMPaint);
begin
  FD2DCanvas.BeginDraw;
  FD2DCanvas.Pen.Color := clRed;
  FD2DCanvas.RenderTarget.DrawGeometry(FGeometry, FD2DCanvas.Pen.Brush.Handle);
  FD2DCanvas.EndDraw;
end;






direct2d