繁体   English   中英

使用 Vulkan 加载/删除动态缓冲区

[英]Loading/removing dynamically buffers with Vulkan

我从 OpenGL 切换到 Vulkan 以使用多线程改进。

在 OpenGL 中,我能够在使用等待系统渲染时将 object 动态加载到场景(缓冲区、纹理等)。 我在一个线程中加载所有应用程序端的东西,然后当它准备好时,就在主线程中的帧渲染之前,我将所有内容发送到视频 memory 中。这很好。

使用 Vulkan,我知道我可以在线程之间调用一些函数,而不会从 OpenGL 引发众所周知的段错误。但是,这不适用于 vkQueueSubmit()。 我已经知道了,我试过天真的方法。 对我来说,你不能打扰来自多个线程的队列似乎是合乎逻辑的。

我有一些想法,但我不知道哪个是好是坏。

首先,我会 go OpenGL 方式,我会从 CPU/App 端准备一切,然后在渲染帧之前,我会提交缓冲区(带传输队列)到视频 memory。但我觉得没有从 OpenGL 方式真正改进......

其次,我将尝试使用同步机制,以便能够在一个线程中发送缓冲区并从另一个线程进行渲染。 但我一直在阅读,有很多方法可以通过导致不相关的锁或使用不正确的信号量和栅栏来减慢一切。

所以我的问题,基本上是选择什么路径来解决这个问题? 如何在主线程渲染时从另一个线程动态加载缓冲区而不会对性能造成太大影响? Vulkan 如何提供帮助?

如果你想立即使用 stream 资源(即主渲染没有它们就无法继续),那么你几乎要阻止主线程等待,或者让它旋转做一些视觉上有趣的事情(例如动画加载屏幕)等待资源加载。

如果你想在应用程序进行实际渲染时使用 stream 资源,那么这里的主要技巧是在后台异步加载资源,并且只有在加载后才切换到在主线程中使用这些资源。 如果主线程最终实际上阻塞在信号量上,那么您可能已经开始丢帧,因此您的“引擎”设计需要确保这种情况永远不会发生。 许多游戏使用简单的低细节代理对象作为替代版本,而高细节版本在后台加载。

这些都与图形 API 没有特别的关系——GL 和 Vulkan 都需要相同的宏观尺度行为。 Vulkan API 功能并没有特别的帮助,因为导致问题的主要瓶颈是 storage.network/CPU,这与问题的图形部分无关。

我决定相信线程!

首先它似乎有效,我得到了很多:

[MESSAGE:Validation Error: [ UNASSIGNED-Threading-MultipleThreads ] Object 0: handle = 0x56414228bad8, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0x141cb623 | THREADING ERROR : vkQueueSubmit(): object of type VkQueue is simultaneously used in thread 0x7f6b977fe640 and thread 0x7f6bc2bcb740]

但它有效!

所以,基本的想法是在引擎绘制时有一个线程来加载对象。 该线程负责为 object 的位置创建 UBO,然后当从 RAM 加载几何图形时,它创建 VBO 和 IBO(我暂时保留带有图像/UBO 的材料),然后创建图形管道(布局,描述符布局,使用 GLSLang 动态编译的着色器)(下一个想法是为类似的需求重用管道)最后设置一个标志来表示 object 已准备好使用。 另一方面,我有我的主线程渲染,并在新对象准备就绪时获取它们。

我认为它有效,因为我有一个带有多个队列设置的温和视频卡 (GTX 1070),我有一个用于图形,另一个用于传输设置。

我很确定,对于具有单个队列的 GPU,这会崩溃或运行不佳,这应该是验证层告诉我这些消息的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM