C++ 渲染调用性能消耗
我的Vulkan程序运行得非常慢,我正试图找出原因。我注意到,即使是一些抽签调用,也会大大降低性能。 例如,以下是用于渲染几个网格的提取(伪代码):C++ 渲染调用性能消耗,c++,performance,rendering,vulkan,C++,Performance,Rendering,Vulkan,我的Vulkan程序运行得非常慢,我正试图找出原因。我注意到,即使是一些抽签调用,也会大大降低性能。 例如,以下是用于渲染几个网格的提取(伪代码): int32_t numCalls = 0; int32_t numIndices = 0; for(auto &mesh : meshes) { auto vertexBuffer = mesh.GetVertexBuffer(); auto indexBuffer = mesh.GetIndexBuffer();
int32_t numCalls = 0;
int32_t numIndices = 0;
for(auto &mesh : meshes)
{
auto vertexBuffer = mesh.GetVertexBuffer();
auto indexBuffer = mesh.GetIndexBuffer();
vk::DeviceSize offset = 0;
drawCmd.bindVertexBuffers(0,1,&vertexBuffer,&offset); // drawCmd = CommandBuffer for all drawing commands (single thread)
drawCmd.bindIndexBuffer(indexBuffer,offset,vk::IndexType::eUint16);
drawCmd.drawIndexed(mesh.GetIndexCount(),1,0,0,0);
numIndices += mesh.GetIndexCount();
++numCalls;
}
正在渲染238个网格,总顶点索引计数为52050。GPU绝对不会负担过重(着色器非常便宜)
如果我用上面的代码运行程序,帧的渲染时间约为46ms。没有它,只需9ms
我正在使用fifo呈现模式和2个交换链图像。此时只有一个主命令缓冲区(无辅助命令缓冲区/预记录缓冲区),所有帧的缓冲区相同
我的问题是,我真的不知道该找什么。这几个渲染调用应该不会造成什么影响,因此问题的根源一定在其他地方
有谁能给我一些建议,我应该如何处理这个问题?Vulkan公司已经有分析人员了吗?我只需要朝正确的方向轻推一下
//编辑:
因此,如果渲染全部238个网格,vkDeviceWaitIdle似乎需要大约32毫秒的时间来执行。(如果没有渲染,则小于1ms)。
大多数的拖延都源于此,但我仍然不知道该怎么办
因此,如果渲染全部238个网格,vkDeviceWaitIdle似乎需要大约32毫秒的时间来执行。(如果没有渲染,则小于1ms)。大多数的拖延都源于此,但我仍然不知道该怎么办
避免使用vkDeviceWaitIdle。这是最沉重的同步操作,将迫使GPU完成并刷新所有工作
尝试使用其他更轻量级的同步对象,如信号量、屏障、围栏和事件,并尽可能窄地指定访问掩码和管道阶段
狭窄的范围,特别是对于管道阶段,确保管道的其他部分可以继续工作,而使用vkDeviceWatiIdle,您可以暂停管道的所有部分。绝对没有理由在渲染循环中使用
vkDeviceWaitIdle
相反,您应该向vkQueueSubmit
调用添加一个vkFence,并使用vkGetFenceStatus
查看是否可以触摸命令缓冲区使用的内存
这将像环形缓冲区一样使用,以便存储可变数据(视图矩阵等)的多个副本,直到GPU处理完它们。
auto vertexBuffer=mesh.GetVertexBuffer()代码>这会导致一个可能成为瓶颈的副本。它不是,而是一个句柄(8字节)。索引缓冲区也是如此。实际的cpp代码基本上对帧时间没有任何影响。vkDeviceWaitIdle
你为什么这么叫?这就像glFinish
;这是你永远不应该做的事。除非您正在进行一次主要的应用程序状态转换(甚至可能不会)或应用程序崩溃。听起来vkDeviceWaitIdle是您的主要问题,但是,您是否启用了验证层?使用VK_LAYER_LUNARG_standard_验证会增加大量开销。