我刚刚了解了统一缓冲区(https://vulkan-tutorial.com/Uniform_buffers/Descriptor_layout_and_bufferuniformBuffers ),并且对和的大小有点困惑uniformBuffersMemory。教程中说:
我们应该有多个缓冲区,因为多个帧可能同时在飞行,我们不想在前一帧仍在读取时更新缓冲区以准备下一帧!我们可以为每帧或每个交换链图像提供一个统一的缓冲区。
据我了解,“每个交换链图像”方法更为优化。如果我是错的,请证明我错了。但为什么我们需要它的大小呢swapChainImages.size()?MAX_FRAMES_IN_FLIGHT仅仅因为我们有栅栏就够了吗?举个简单的例子,如果我们只有一个正在运行的帧并在vkDeviceWaitIdle每次演示后执行,那么我们的单个统一缓冲区将始终可用并且不会被 cpu/gpu 使用,因此我们不需要它们的数组。
做
vkDeviceWaitIdle
好吧,就停在那里。调用该函数基本上只有一个正当理由:您需要删除该设备创建的所有资源,因为您要销毁该设备,因此您要等到所有此类资源不再被使用。
是的,如果您停止 CPU 的执行,直到 GPU 停止执行操作,那么就可以保证 CPU 对 GPU 内存的写入不会与 GPU 从该内存的读取交互。但是您通过确保CPU 执行和 GPU 执行之间完全不存在重叠来购买此保证。CPU 设置一些东西,将其发送到 GPU,然后等待 GPU 完成,CPU 再次启动。一切都完美同步执行。当 CPU 工作时,GPU 不执行任何操作。反之亦然。
这不是提高绩效的秘诀。如果您打算使用旨在实现大量 CPU/GPU 重叠的图形 API,您不应该丢弃它,因为它更容易使用。
习惯对定期从 CPU 修改的任何资源进行多重缓冲。您想要使用多少个缓冲区是您的选择,应该由当前模式等告知。
我的问题是“我需要 n 个缓冲区还是 m 就足够了?”。
您所描述的情况最终仅在您的代码想要有 X 帧在飞行中时才会发生,但演示引擎要求您使用最少的 Y 交换链图像,并且 X < Y。所以您提出的问题可以归结为,“如果我想做双缓冲,但实现强制我使用 3 个缓冲区,我可以将其视为双缓冲吗?”
是的,只要您不依赖调用vkAcquireNextImage来阻止 CPU 进行同步即可。但无论如何您都不应该依赖它,因为就 Vulkan 执行模型而言,调用本身并不构成适当的障碍。相反,您应该在与实际工作相关的栅栏上阻塞 CPU,而不是在获取进程上。