5

私はIDirect3DSurface9、デフォルトプール、YUVフォーマットを持っています。どうすれば効率的にビットマップビットを取得できますか?現時点では私は:

    レンダリングターゲットを作成します。
    device->CreateRenderTarget(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL)
    YUVをRGB32に変換:(
    device->StretchRect(videomem_surf, NULL, render_target_, NULL, D3DTEXF_NONE)
    完全な長方形、ストレッチなし)
    システムメモリにプレーンなオフスクリーンサーフェスを作成する
    device->CreateOffscreenPlainSurface(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sysmem_offscreen_surf, NULL)
    ビデオメモリからsysmemにデータをコピーします。
    device->GetRenderTargetData(render_target, sysmem_offscreen_surface)
    オフスクリーンサーフェスからGetDC、互換性のあるDCおよび互換性のあるビットマップを作成し、オフスクリーンの表面DCから互換性のあるDCにBitBltを作成し、GetDIBits()によってビットマップビットをバッファーにコピーします

元のサーフェスからレンダリングターゲット、次にオフスクリーンサーフェス、互換性のあるビットマップ、最後にバッファへのコピーが非常に多いため、これは少しオーバーヘッドに見えます。これをどのように改善できますか?

ありがとう

4

2 に答える 2

4

インタージェイが指摘するように...あなたはほとんど「正しい」方法で物事をやっています。

明らかな改善点は、CreateRenderTargetとCreateOffscreenPlainSurfaceを一度呼び出してから、それらを複数回再利用することです。ビットを元に戻す最も速い方法は、サーフェスを直接LockRectすることです。

さらに、ビデオのようなものでこれをリアルタイムで行う必要がある場合は、サーフェスの配列(両方のタイプ)を設定する方がおそらく良いでしょう。次に、複数のYUVフレームをCreateRenderTargetのサーフェスにロードし、配列を埋めたら、最初のフレームをOffscreenPlainSurfaceにコピーしてロックします。

このようにして、より多くのコマンドをパイプライン化できるようにし、ロックの呼び出しとパイプラインの同期の強制を停止します(つまり、ロックしているサーフェスは、先に進む前に準備ができている必要があり、パイプラインの同期が発生します)。

于 2010-12-14T07:38:00.237 に答える
3

レンダーターゲットをロック可能モード(への6番目のパラメーターCreateRenderTarget)で作成するので、レンダーターゲットをでロックしLockRect、そこからデータを直接コピーできます。

MSDNは、ロック可能なレンダリングターゲットの使用を推奨しておらず、次のように述べています

レンダーターゲットに読み取りアクセスが必要な場合は、ロック可能なレンダーターゲットの代わりにGetRenderTargetDataを使用してください。

したがって、別の方法は、オフスクリーンサーフェスを呼び出しGetRenderTargetDataてから、オフスクリーンサーフェスをロックすることです(DCとビットマップを使用する代わりに)。

于 2010-12-13T18:30:51.097 に答える