Direct2dオフスクリーンレンダリングとハードウェアアクセラレーション


7

私はdirect2dを使用して、WindowsAPICodePackを使用して画像を画面外にレンダリングしようとしています。これは、WicBitmapRenderTargetを使用して簡単に実現できますが、残念ながらハードウェアアクセラレーションではありません。

だから私はこのルートを試しています:

  1. direct3dデバイスを作成する
  2. texture2dを作成する
  3. テクスチャサーフェスを使用して、CreateDxgiSurfaceRenderTargetを使用してレンダーターゲットを作成します。
  4. いくつかの形を描く

これにより画像がレンダリングされますが、CPUの使用率が高い間はGPUがまったく使用されていないように見えます。

私は何か間違ったことをしていますか?ハードウェアまたはソフトウェアのレンダリングが使用されているかどうかを確認する方法はありますか?

コードサンプル:

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();
}

回答:


5

Direct2Dは、GPUを使用しないように指定しない限り、GPUを使用していますが、残念ながら、Direct2Dは実際には期待したほど効率的ではありません。同様の質問がgamedevフォーラムでありました接続された線を描く最も速い方法は?」私はテストケースでテストを再度実行しましたが、結果は少し怖いです...

画面に10000の楕円(サイズ10,10)を描画しようとしているとき、GPUは事実上次のものを受け取ります。

  • レンダリングターゲットでアンチエイリアスモードをオフにした場合、1,500,000の頂点=> 500,000の三角形でレンダリング
  • レンダリングする4,411,734頂点=> 1,470,578の三角形、アンチエイリアスモードが有効(デフォルトでは)

ジオメトリは事前にわからないため、renderTarget.BeginDrawとEndDrawの間でDrawEllipseを呼び出すたびに、CPUで実行する必要があるDirect2Dコードの一部は、それらのすべての頂点を生成する必要があるため、非常に負荷が高くなります(楕円形の外側の線をカバーするために表面全体に小さな三角形を生成し、すべてのコマンドをGPUに送信します(数百のDirect3D10コマンド)。各三角形は、実際にはほぼピクセル領域をカバーしています。

AntiAliasedモードをオフにすることでCPU使用率を下げることができますが、エイリアシングを減らすにはAntiAliasedポストエフェクトシェーダーを使用する必要があります。

これを自分で確認するために、DirectX SDKから入手可能なPIXデバッガーを使用してアプリケーションを実行できます。

余談ですが、WindowsAPICodePackは実際には効率的ではなく、アクティブに保守されていないAPIであるため、使用しないでください。すべてのDirect2D / DirectWrite機能をサポートしているSharpDXを使用することをお勧めします(他のマネージAPIでサポートされていないテッセレーション用のコールバックなど)。


お時間をいただきありがとうございます。そして、SharpDXの提案に感謝します。私のユースケースでプロジェクトをテストします...
Goran

あなたの答えは基本的にそれをカバーしていますが、AAには3番目のオプションがあります。D2Dアンチエイリアスをオフにして、MSAA D3Dターゲットにレンダリングしてから、ResolveSubresourceを使用できます。これにより、D2Dの分析方法と同様の品質が得られますが、パフォーマンスは大幅に向上します。
Lucas

@Lucas、確かにMSAAのは、ポストエフェクトを使用するよりも少ないセットアップを必要とするなどFXAA、SMAA ...などアンチエイリアシング技術
xoofx

1

ハードウェアアクセラレーションを使用しますが、GPUは可視領域に描画されないため、はるかに少なく使用されます。GPUの使用はカードのパフォーマンスに依存するため、これをハイエンドで試しても、GPUの使用はほとんどありません。(十分なCPUパワーを備えた)ローエンドでそれを試すと、使用率は魔法のように上がります。

したがって、GPUの使用状況により、accがオンかどうかがわかります。RenderTargetTypeがデフォルトの場合、サポートされていればアクセラレーションが使用されます。ハードウェアを設定すると、それが使用されるか、そうでなければエラーになります。

とにかく、Direct3Dを使用していない場合は、BitmapRenderTargetおよびd2dbitmapをオフスクリーンバッファーとして使用する必要があります。そのより速い。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.