2016-09-13 8 views
0

私はレンダリングする要素のリストをソートするRenderQueueを持っています。 RenderQueueがすべての「低レベル」レンダリング操作を含むRenderCommandBufferを作成したので、1000要素の場合、パフォーマンスが1400 FPSから40FPSになるという問題がありました。RenderCommandBufferにRenderコマンドを挿入するヒープ割り当てを避けるには?

私はこのアプリケーションをプロファイリングしました。 ):

 std::for_each(element.meshCommands.begin(), element.meshCommands.end(), [&] (auto &command) { 
      std::vector<std::pair<std::string, glm::mat4> > p{ { "MVP", VPmatrix * command.second} }; 
      m_commandBuffer.addCommand(std::make_shared<SetShaderValuesCommand>(element.material,p)); 
      m_commandBuffer.addCommand(std::make_shared<BindMaterialCommand>(element.material)); 
      m_commandBuffer.addCommand(std::make_shared<RenderMeshCommand>(meshProperty.mesh)); 
     }); 

材料でメッシュをグループ化できますが、問題は多かれ少なかれ同じです。フレームごとに多くのオブジェクトを割り当てる。この状況をどうやって避けるのですか?どのようにゲームエンジンがこの問題に対処していますか?メモリプール?

+1

カスタムアロケータ。そこにいくつかの図書館と話があります。 EAはオープンソースのソースも持っています。https://github.com/electronicarts/EASTL – Hayt

+5

なぜこのようなことですべてのものの 'shared_ptr'を使用していますか? –

+0

また、アプリケーションのビルドに使用したコンパイラオプション、特に最適化設定を投稿してください。これがテストする "デバッグ"または最適化されていないビルドの場合、結果は無意味です。 – PaulMcKenzie

答えて

2

詳細はほとんどありませんが、チューニングの機会は2つあります。

m_commandBufferは多種多様な容器です。私はあなたがそれをこのように構築する理由を完全に理解していますが、それは問題を提示します - 各要素は別々に割り当てられなければなりません。

すべてのレンダリング操作をvariantに統合し、そのようなバリアントのベクトル(またはキュー)としてm_commandBufferを実装すると、はるかに優れたパフォーマンスが得られます。これにより、現在必要な(少なくとも)1000ではなく、1つのメモリ割り当てで1000コマンド用のスペースがreserve()になります。

shared_ptrのすべての参照カウントを増分したり減分したりしている間に、割り当て中に1つのメモリフェンスのコストが発生するだけではなく、何千もの問題が発生することもあります。だから、

:コマンドを実行

using Command = boost::variant< SetShaderValuesCommand, BindMaterialCommand, RenderMeshCommand>; 

using CommandQueue = std::deque<Command>; 

は、次のようになります。通常

for (auto& cmd : m_commandBuffer) { 
    boost::apply_visitor([](auto& actualCmd) { 
    actualCmd.run(); /* or whatever is the interface */ 
    }, cmd); 
} 
+0

ありがとう、私はstd :: variantを発見しました。問題は今私のコマンドがPODではないということです。私のコマンドがstd :: stringやstd :: vectorのような型を保持していれば、これはうまくいかないと思います。 PODタイプだけを保持するようにコマンドを変更した後、このアプローチを試してみます。ありがとうございました!! – FrameBuffer

+0

@FrameBuffer非PODタイプでも動作します。彼らは移動可能でなければならず、移動可能でなければなりません。 –

+0

しかし、これらのタイプはコンテンツを割り当てないために内部的に "new"を呼び出します。これはパフォーマンスに影響しますか、間違っていますか? – FrameBuffer

関連する問題