5

Linuxに移植中のエミュレーターを作成しました。現在、ビデオを作成するために、OpenGL(現在Windowsで実行している)に移植しているDirect3D11を使用しています。フレームごとにメモリにアップロードする1024x1024テクスチャにレンダリングします(元のハードウェアは実際には最新のハードウェアアクセラレーションに適していないため、すべてソフトウェアで実行します)。ただし、OpenGLでのテクスチャのアップロードは非常に遅いことがわかりました。

Direct3Dでテクスチャをアップロードすると、フレームごとにフレームレートが416から395に低下します(5%低下)。OpenGLでは、427から297に低下します(30%低下します!)。

これが私の描画関数からの関連コードです。

Direct3D:

D3D11_MAPPED_SUBRESOURCE resource;
deviceContext_->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
uint32_t *buf = reinterpret_cast<uint32_t *>(resource.pData);
memcpy(buf, ...);
deviceContext_->Unmap(texture, 0);

OpenGL:

glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA,
    GL_UNSIGNED_BYTE, textureBuffer);

誰かがこの減速を引き起こしている可能性があるものを提案できますか?

それがうまくいかない場合は、NVIDIA GeForce GTX550Tiを搭載したWindows7x64を実行しています。

4

2 に答える 2

11

glTexImage2D(GL_TEXTURE_2D、0、GL_RGBA、1024、1024、0、GL_RGBA、GL_UNSIGNED_BYTE、textureBuffer);

あなたはここでいくつか間違ったことをしています。まず、フレームごとにDirect3Dテクスチャリソースを作成glTexImage2Dするのと同じです。しかし、あなたはそれを作成していません。アップロードしているだけです。対象のミップマップレイヤーごとに1回だけ使用する必要があります。その後、すべてのアップロードはで発生するはずです。glTexImage2DglTexSubImage2D

次に、内部形式(左から3番目のパラメーター)はGL_RGBAです。画像形式には常に明示的なサイズを使用する必要があります。したがって、を使用しますGL_RGBA8。これは実際には問題ではありませんが、今すぐ習慣を身につける必要があります。

第三に、ピクセル転送フォーマットGL_RGBAの順序付けを使用しています(左からではなくから3番目のパラメーター)。多くのハードウェアは順序付けを好む傾向があるため、これは一般的に最適なピクセル転送形式ではありません。しかし、その順序でデータを生成しているものからデータを取得していない場合、実行できることはあまりありません。GL_BGRA

第4に、アップロードを開始してから実際にレンダリングするまでの間に他にできることがある場合は、非同期のピクセル転送操作を使用できます。データをバッファオブジェクトに書き込みます(マッピングできるため、コピーする必要はありません)。次に、を使用glTexSubImage2DしてこのデータをOpenGLに転送します。glTexSubImage2Dソースデータと宛先イメージはOpenGLのメモリの一部であるため、戻る前にクライアントメモリからデータをコピーする必要はありません。

確かに、D3Dの場合はすでにそのコピーを効果的に行っているので、それはおそらくあまり役​​に立ちません。

OpenGLでは、427から297に低下します(30%低下します!)

より重要な統計は、1ミリ秒の差であるということです。タイミングは、1秒あたりのフレーム数や、FPSの低下率ではなく、絶対時間で確認する必要があります。

于 2012-10-16T20:53:24.713 に答える
7

glTexImage2dは、メモリの再割り当てと更新を行います。代わりにglTexSubImage2dを使用してみてください。

于 2012-10-16T20:40:03.930 に答える