Kết xuất ngoài màn hình Direct2d và tăng tốc phần cứng


7

Tôi đang cố gắng sử dụng direct2d để hiển thị hình ảnh ngoài màn hình bằng WindowsAPICodePack . Điều này có thể dễ dàng đạt được bằng cách sử dụng WicBitmapRenderTarget nhưng đáng buồn là nó không được tăng tốc phần cứng.

Vì vậy, tôi đang thử tuyến đường này:

  1. Tạo thiết bị direct3d
  2. Tạo texture2d
  3. Sử dụng bề mặt kết cấu để tạo mục tiêu kết xuất bằng CreatDxgiSurfaceRenderTarget
  4. Vẽ một số hình

Mặc dù điều này thể hiện hình ảnh nhưng có vẻ như GPU không được sử dụng trong khi CPU được sử dụng rất nhiều.

Tôi có làm điều gì sai? Có cách nào để kiểm tra xem phần cứng hoặc phần mềm kết xuất được sử dụng không?

Mẫu mã:

var device = D3DDevice1.CreateDevice1(null,
                DriverType.Hardware,
                null,
                CreateDeviceOptions.SupportBgra,
                FeatureLevel.Ten
                );

var txd = new Texture2DDescription();
txd.Width = 256;
txd.Height = 256;
txd.MipLevels = 1;
txd.ArraySize = 1;
txd.Format = Format.B8G8R8A8UNorm; //DXGI_FORMAT_R32G32B32A32_FLOAT;
txd.SampleDescription = new SampleDescription(1,0);
txd.Usage = Usage.Default;
txd.BindingOptions = BindingOptions.RenderTarget | BindingOptions.ShaderResource;
txd.MiscellaneousResourceOptions = MiscellaneousResourceOptions.None;
txd.CpuAccessOptions = CpuAccessOptions.None;

var tx = device.CreateTexture2D(txd);

var srfc = tx.GraphicsSurface;

var d2dFactory = D2DFactory.CreateFactory();

var renderTargetProperties = new RenderTargetProperties
{
    PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied),
    DpiX = 96,
    DpiY = 96,
    RenderTargetType = RenderTargetType.Default,
};

using(var renderTarget = d2dFactory.CreateGraphicsSurfaceRenderTarget(srfc, renderTargetProperties))
{
    renderTarget.BeginDraw();
    var clearColor = new ColorF(1f,1f,1f,1f);
    renderTarget.Clear(clearColor);
    using (var strokeBrush = renderTarget.CreateSolidColorBrush(new ColorF(0.2f,0.2f,0.2f,1f)))
    {
        for (var i = 0; i < 100000; i++)
        {
            renderTarget.DrawEllipse(new Ellipse(new Point2F(i, i), 10, 10), strokeBrush, 2);
        }
    }

    var hr = renderTarget.EndDraw();
}

Câu trả lời:


5

Direct2D đang sử dụng GPU trừ khi bạn chỉ định không sử dụng nó ... nhưng thật không may, Direct2D trên thực tế không hiệu quả như chúng ta mong đợi. Có một câu hỏi tương tự trên diễn đàn gamedev " Cách nhanh nhất để vẽ các đường kết nối? " Tôi đã chạy lại bài kiểm tra trên trường hợp thử nghiệm của bạn và kết quả lại hơi đáng sợ ...

Khi bạn đang cố vẽ 10000 hình elip trên màn hình (kích thước 10,10), GPU sẽ nhận được một cách hiệu quả:

  • 1.500.000 đỉnh => 500.000 hình tam giác để kết xuất, nếu bạn tắt chế độ khử răng cưa trên mục tiêu kết xuất
  • 4.411.734 đỉnh => 1.470.578 hình tam giác để hiển thị, với chế độ antialias được bật (theo mặc định trong trường hợp của bạn)

Bởi vì hình học không được biết trước, bất cứ khi nào bạn gọi DrawEllipse giữa renderTarget.BeginDraw và EndDraw, phần mã Direct2D cần chạy trên CPU khá chuyên sâu, vì nó cần phải tạo ra tất cả các đỉnh đó (Nó như để tam giác hóa toàn bộ bề mặt và tạo ra các hình tam giác nhỏ để che đi đường ngoài của hình elip) và gửi tất cả các lệnh tới GPU (vài trăm lệnh Direct3D10). Mỗi tam giác trên thực tế bao phủ gần như một vùng pixel.

Bạn có thể giảm mức sử dụng CPU bằng cách chuyển chế độ AntiAliased, nhưng sau đó bạn sẽ phải sử dụng các trình tạo bóng hậu hiệu ứng AntiAliased để giảm răng cưa.

Để tự kiểm tra điều này, bạn có thể chạy ứng dụng của mình với trình gỡ lỗi PIX có sẵn từ DirectX SDK.

Mặt khác, bạn không nên sử dụng WindowsAPICodePack, vì đây là một API không thực sự hiệu quả và không được bảo trì tích cực. Tôi sẽ đề nghị bạn sử dụng SharpDX , hỗ trợ tất cả các tính năng Direct2D / DirectWrite (bao gồm cả các cuộc gọi lại, ví dụ như cho tessname, không được hỗ trợ bởi bất kỳ API được quản lý nào khác).


Cảm ơn bạn đã dành thời gian. Và cảm ơn lời đề nghị của SharpDX. Sẽ thử nghiệm dự án trên usecase của tôi ...
Goran

Câu trả lời của bạn về cơ bản bao gồm nó, nhưng có một tùy chọn thứ 3 cho AA. Bạn có thể tắt AntiDiasing D2D nhưng kết xuất với mục tiêu MSAA D3D và sau đó sử dụng ResolveSubresource. Tôi đã thấy rằng điều này dẫn đến chất lượng tương tự như phương pháp phân tích của D2D nhưng với sự hoàn hảo tốt hơn nhiều.
Lucas

@Lucas, thực sự đối với MSAA vì Nó yêu cầu thiết lập ít hơn so với sử dụng các kỹ thuật khử răng cưa sau hiệu ứng như FXAA, SMAA ... vv
xoofx

1

Nó không sử dụng khả năng tăng tốc phần cứng, nhưng GPU được sử dụng ít hơn nhiều vì không có bản vẽ vào khu vực có thể nhìn thấy. Việc sử dụng GPU phụ thuộc vào hiệu suất của thẻ, vì vậy nếu bạn thử điều này trên highend, sẽ thực sự có ít GPU sử dụng. Khi bạn thử điều đó ở mức thấp (có đủ sức mạnh CPU), việc sử dụng sẽ tăng lên một cách kỳ diệu.

Vì vậy, việc sử dụng GPU sẽ cho bạn biết nếu acc được bật. Nếu RenderTargetType là mặc định, tăng tốc sẽ được sử dụng nếu được hỗ trợ. Nếu bạn đặt phần cứng, nó sẽ được sử dụng hoặc lỗi khác.

Dù sao, nếu bạn không sử dụng Direct3D, bạn nên sử dụng BitmapRenderTarget và d2dbitmap làm bộ đệm ngoài màn hình. Nó nhanh hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.