渲染调用性能消耗
Render-call performance drain
我的Vulkan程序运行速度非常慢,我正在努力找出原因。我注意到,即使是几次平局也已经大大消耗了性能。例如,这里有一个用于渲染一些网格的摘录(伪代码):
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似乎需要大约32ms才能执行。(如果没有渲染,则为<1ms)。大多数停滞都源于此,但我仍然不知道该怎么办。
因此,如果渲染了所有238个网格,那么vkDeviceWaitIdle似乎需要大约32ms才能执行。(如果没有渲染,则为<1ms)。大多数拖延都源于此,但我仍然不知道该怎么办
避免使用vkDeviceWaitIdle。这是可用的最重的同步操作,将迫使GPU完成并刷新所有工作。
尝试使用其他更轻量级的同步对象,如信号量、屏障、围栏和事件,并指定范围尽可能窄的访问掩码和管道阶段。
狭窄的范围,特别是对于管道阶段,可以确保管道的其他部分可以继续工作,而对于vkDeviceWatiIdle,您可以暂停管道的所有部分。
绝对没有理由在渲染循环中使用vkDeviceWaitIdle
。
相反,您应该在vkQueueSubmit
调用中添加一个vkFence,并使用vkGetFenceStatus
查看是否可以触摸命令缓冲区使用的内存。
这将像环形缓冲区一样使用,因此存储可变数据(视图矩阵等)的多个副本,直到GPU处理完它们。
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 虚拟函数调用的性能作为 for 循环中的上限
- 性能函数调用与乘以 1
- if-else 与三元函数调用性能
- 在类实例或方法的上下文中调用函数以进行性能分析
- 当我将 c++ DLL(我从 c# 调用)重新生成为 /CLR(最初是本机)时,性能下降了一半
- 在X64模式下从C /CLI调用MASM PROC会产生意外的性能问题
- constexpr vs重复函数调用性能
- C++按字符串调用函数,比较PHP的性能,如何在C++中优化代码
- 递归可变参数函数调用对简单 if.else 语句的性能
- 尾部调用优化似乎略微降低了性能
- C /C#Interop中的内存映射和P/调用性能
- 运算符重载与函数调用的性能
- 奇怪的OpenCL调用C++上的副作用来提高循环性能
- 渲染调用性能消耗
- 对同一对象进行x调用的c++虚拟函数性能
- C++纯虚拟函数调用的性能可变性
- 调用GPU内核后,CPU性能下降
- 嵌套函数或方法调用会降低应用程序的性能
- 可以通过减少多线程中系统调用(互斥/信号量)的开销来真正提高性能::atomic