2017-05-10 29 views
8

Vì lý do lạ, hãy gọi hàm ExtTextOutW của WinAPI để vẽ văn bản được cắt bớt trên bitmap có độ phân giải cao (2560x1440/3840x2160) dẫn đến hiệu suất ~ x50 sau khi cập nhật Windows 10 với bản cập nhật phiên bản Người sáng tạo. Từ các bản ghi kiểm tra và gỡ lỗi của người dùng của tôi, có vẻ như một sự khác biệt nhỏ trong bitmap hoặc kích thước phông chữ có thể kích hoạt hiệu suất đạt được.Giảm bớt hiệu suất ExtTextOutW x50 trên màn hình QHD/4K sau khi cập nhật phiên bản Windows Creators

Đây là một bản ghi gỡ lỗi hiển thị hiệu suất hit:

10/05/2017 15:51:50 [ 63227,186] : Calculate Rect 
10/05/2017 15:51:50 [ 63227,190] : Rect : Left=263, Top=504, Right=3561, Bottom=2155 
10/05/2017 15:51:50 [ 63227,193] : Set Shadow Color 
10/05/2017 15:51:50 [ 63227,198] : Render Text Shadow 
10/05/2017 15:51:50 [ 63236,650] : Set Text Color 
10/05/2017 15:51:50 [ 63236,661] : Render Text "Kingdom come Deliverance" 
10/05/2017 15:51:50 [ 63246,062] : Rendering complete 

Như bạn có thể nhìn thấy từ nhật ký, một cuộc gọi duy nhất để ExtTextgOutW mất ~ 9.5ms khi cuộc gọi này cùng mất tốt dưới 1ms trước khi những người sáng tạo cập nhật.

Đây là mã thực tế mà bạn có thể so sánh với các kết xuất debug trên:

{$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Calculate Rect');{$ENDIF} 
    cRect := Rect(X,Y,Width+X,MainForm.Monitor.Height-(1+(MainForm.Monitor.Height div 540))); 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Rect : Left='+IntToStr(cRect.Left)+', Top='+IntToStr(cRect.Top)+', Right='+IntToStr(cRect.Right)+', Bottom='+IntToStr(cRect.Bottom));{$ENDIF} 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Set Shadow Color');{$ENDIF} 
    srcColor := txtCanvas.Font.Color; 
    txtCanvas.Font.Color := OutLineColor; 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Render Text Shadow');{$ENDIF} 
    Windows.ExtTextOutW(txtCanvas.Handle,X ,Y+(MainForm.Monitor.Height div 540),ETO_CLIPPED,@cRect,@S[1],I,nil); 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Set Text Color');{$ENDIF} 
    txtCanvas.Font.Color := srcColor; 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Render Text "'+S+'"');{$ENDIF} 
    Windows.ExtTextOutW(txtCanvas.Handle,X ,Y ,ETO_CLIPPED,@cRect,@S[1],I,nil); 
    {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:\log\.TextRender.txt','Rendering complete'+CRLF);{$ENDIF} 

Mã này không ảnh hưởng thả bóng rất đơn giản bằng cách làm cho các văn bản cùng một hai lần với một khác biệt nhỏ trong Y- Bù đắp và màu sắc.

Đây là thảo luận đầy đủ với người dùng diễn đàn của tôi, nơi chúng tôi cố gắng để gỡ lỗi vấn đề này trên một loạt các phần cứng (thêm các bản ghi gỡ lỗi có trong bài): http://forum.inmatrix.com/index.php?showtopic=14995&page=2

Chúng tôi thử nghiệm với DPI thiết lập để 100 % để đảm bảo trình kích hoạt không liên quan đến các thay đổi DPI được giới thiệu trong Ấn bản dành cho người sáng tạo.

Có ai biết điều gì kích hoạt điều này không? và có một công việc xung quanh?

***** cập nhật 1 *****

Ít nhất trong thử nghiệm ban đầu, "DrawTextExW" cũng có vẻ bị ảnh hưởng bởi mất hiệu suất. Phông chữ được sử dụng trong quá trình thử nghiệm là Arial và các vấn đề hiệu suất dường như có liên quan đến kích thước của phông chữ khi người dùng báo cáo rằng thêm nhiều dòng có kích thước thấp hơn vào màn hình (văn bản được hiển thị ở độ phân giải thấp hơn) cải thiện hiệu suất rất nhiều.

***** cập nhật 2 *****

Tôi đã viết một công cụ nhỏ để hồ sơ vấn đề này mà bạn có thể tìm thấy trong kho lưu trữ GitHub này: https://github.com/bLightZP/WindowsTextRenderingProfiler

Có vẻ như vấn đề này phụ thuộc vào kích thước phông chữ, ví dụ: trên màn hình 2560x1440, hiển thị một dòng văn bản phông chữ "Arial" có kích thước "35" 21 mili giây để hiển thị trong khi kích thước "34" mất 2ms.

Điều này được hiển thị với HDC của một TBitmap Delphi với định dạng pixel 32 bit và việc tắt cắt chỉ có ảnh hưởng nhỏ đến hiệu suất.

***** cập nhật 3 *****

Sebastian Z của câu trả lời dưới đây không khôi phục trước người sáng tạo trình độ phiên bản của hiệu suất và tôi đã cập nhật các mẫu mã trên GitHub để phản ánh câu trả lời của mình, nhưng tôi có kể từ khi có thể tái tạo vấn đề với Windows 7 64bit và trên màn hình 1920x1080, vì vậy nó không bị giới hạn đối với phiên bản Windows 10 hoặc màn hình độ phân giải cao, chỉ cần ngưỡng kích hoạt cao hơn khi chất lượng phông chữ được đặt thành ANTIALIASED. Trong thử nghiệm của tôi trong Windows 7, sử dụng phông chữ Arial, điểm kích hoạt là kích thước phông chữ "109" (nhanh) so với kích thước phông chữ "110" (hiệu suất chậm hơn hoặc chậm hơn x10). Và ngưỡng kích hoạt tương tự này tồn tại trong Windows 10 sau khi sử dụng câu trả lời của Sebastian Z để vô hiệu hóa cleartype.

+4

Bạn có nhận được hiệu suất giảm tương tự khi bạn xóa cờ ETO_CLIPPED không? Độ sâu màu nào là bitmap (i. E. 24bpp hoặc 32bpp)? Nó là DIB hay DDB? Sẽ tốt nhất nếu bạn thêm [mcve] để người dùng SO có thể cố gắng tái sản xuất. – zett42

+0

Tôi đã cập nhật bài đăng gốc bằng liên kết tới dự án GitHub bao gồm mã nguồn và tệp thực thi mà bạn có thể sử dụng để kiểm tra điều này. Bản cập nhật bao gồm các chi tiết khác. – bLight

Trả lời

4

Delphi tạo phông chữ với lfQuality := DEFAULT_QUALITY;. Chất lượng mặc định được sử dụng để có chất lượng chống răng cưa. Nhưng kể từ khi Windows 10 người sáng tạo cập nhật điều này bây giờ mặc định để cleartype. Và điều này khá chậm. Vì vậy, giải pháp là tự buộc chất lượng chống răng cưa.

Nếu bạn đang sử dụng một phiên bản Delphi hiện sau đó bạn chỉ có thể thiết lập thuộc tính Font.Quality:

Procedure RenderText(oBitmap : TBitmap; X,Y : Integer; cRect : TRect; S : WideString; testFunction : Integer; TxtEffect : Integer; EffectColor : TColor; Clipping : Boolean); 
// [...] 
begin 
    obitmap.Canvas.Font.Quality := fqClearType; 

Trong các phiên bản Delphi cũ nó là một chút phức tạp hơn:

var 
    lf: TLogFont; 
begin 
    if GetObject(oBitmap.Canvas.Font.Handle, SizeOf(TLogFont), @lf) = sizeof(TLogFont) then 
    begin 
    lf.lfQuality := ANTIALIASED_QUALITY; 
    oBitmap.Canvas.Font.Handle := CreateFontIndirect(lf); 
    end; 

này là một bản cập nhật trong Windows 10 Creators Update, bởi vì văn bản ClearType không phải lúc nào cũng phù hợp và có thể dẫn đến kết quả không mong muốn.

+0

Câu trả lời của bạn hoạt động và trả về mức hiệu suất của phiên bản trước người sáng tạo, nhưng với thử nghiệm sâu hơn, có vẻ như vấn đề vẫn tồn tại như Windows 7 nhưng với ngưỡng cao hơn, hãy xem cập nhật 3 (trong khoảng 5 phút) – bLight

Các vấn đề liên quan