如何避免将Rendercommands插入RenderCommandBuffer的堆分配?

时间:2016-09-13 14:54:04

标签: c++ c++11 memory game-engine heap-memory

我有一个RenderQueue,可以对要渲染的元素列表进行排序。 现在RenderQueue创建了一个具有所有“低级”渲染操作的RenderCommandBuffer,问题是1000个元素的性能从1400 FPS到40FPS

我描述了应用程序,问题出在这里(每帧分配​​):

        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 个答案:

答案 0 :(得分:2)

细节很少,但我看到两个调整的机会。

m_commandBuffer是某种多态容器。我完全理解你为什么要用这种方式构建它,但它提出了一个问题 - 每个元素必须单独分配。

通过将所有渲染操作合并到variant中,可以获得更好的性能,并将m_commandBuffer实现为此类变体的向量(或队列)。这允许您为1000个命令reserve()空间分配1个内存,而不是当前需要的(至少)1000个。

这也意味着你只需要在分配期间承担一个内存栅栏的成本,而不是在增加和减少所有shared_ptr s中的所有引用计数时你所遭受的成千上万。

所以:

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