Vulkan Device Lost = 缺少同步,但我不知道如何
Vulkan Device Lost = Missing Synchronization, but I don't know how
我想弄明白,如何使用光线追踪。我所拥有的是一个光栅化器绘制的三角形(与 Vulkan 教程中显示的大部分相同,但重构为我自己的代码和实用程序函数)。由于 window resizing/minimizing 等原因,交换链的重建工作正常。
然后我添加了底部加速结构的创建。从那以后,我遇到了一些“设备丢失”错误,但并非总是如此……这是我的代码框架:
mainLoop:
- acquireNextImage
- renderWorld
- render gui
- present
acquireNextImage:
- signaling a semaphore "Image Available"
render gui:
- wait for fence "Gui"
- begin command buffer (use graphics queue)
- begin render pass
- bind pipeline (graphics)
- set viewport
- set scissor
- draw (2 triangles in my GUI yet)
- end render pass
- end command buffer
- reset fence "Gui"
- submit command buffer (waiting for semaphore "Image Available", signaling semaphore "Rendering Done", checking fence "Gui")
present:
- queue present (waiting for semaphore "Rendering Done")
renderWorld:
(actually this does not render anything yet, it just creates a vertex buffer, an index buffer, and creates the bottom acceleration strucutre for it - and caches it for further frames, so this code runs only once at start!)
- == vertexbuffer ==
- create buffer (usage transfer dst)
- get buffer memory requirements
- allocate memory (device local)
- bind buffer memory
- create buffer (usage transfer src) (this is my staging buffer)
- get buffer memory requirements
- allocate memory (host visible, host coherent) (this is my staging memory)
- bind buffer memory
- wait for fence "Transfer"
- begin command buffer (use dedicated transfer queue)
- copy buffer
- end command buffer
- reset fence "Transfer"
- submit command buffer (checking fence "Transfer")
- wait queue idle
- free stating memory
- destroy staging buffer
- == indexbuffer ==
- create buffer (usage transfer dst)
- get buffer memory requirements
- allocate memory (device local)
- bind buffer memory
- create buffer (usage transfer src) (this is my staging buffer)
- get buffer memory requirements
- allocate memory (host visible, host coherent) (this is my staging memory)
- bind buffer memory
- wait for fence "Transfer"
- begin command buffer (use dedicated transfer queue)
- copy buffer
- end command buffer
- reset fence "Transfer"
- submit command buffer (checking fence "Transfer")
- wait queue idle
- free stating memory
- destroy staging buffer
- == bottom acceleration structure ==
- get acceleration structure build sizes info
- create buffer (acceleration structure storage, shader device address)
- create acceleration structure (bottom level)
- create buffer (acceleration structure storage, shader device address) (this is my scratch buffer)
- wait for fence "BuildAcc"
- begin command buffer (use dedicated compute queue)
- pipeline barrier (transfer write -> acceleration structure write), don't know if I need it here
- build acceleration structures
- pipeline barrier (acceleration structure write -> shader read), don't know if I need it here
- end command buffer
- reset fence "BuildAcc"
- submit command buffer (checking fence "BuildAcc")
- wait queue idle <------- here device lost
- destroy scratch buffer
所以,如果我注释掉“renderWorld”,一切正常。如果我让 renderWorld 进入,那么我会丢失一个设备(请参阅最后的“等待队列空闲”行)。但不是每次我运行程序。
如果我在“wait queue idle”这一行下了一个断点,当程序停在这一行后,我可以继续执行程序,一切都很好。另外,如果我注释掉“build acceleration structures”命令,一切正常(当然除了没有 acc 结构,但没有设备丢失)。
所以我不知道,问题出在哪里。在我看来,我需要以某种方式同步一些东西,因为有了断点我可以 运行 它并且它可以工作。所以我理解的代码一定没问题。
除了缺少着色器绑定外,也没有验证错误,但因为我还没有使用它们(我还没有光线追踪渲染),我应该不是问题。
设备丢失后,其他信号量没有重置,我的 gui 渲染路径也不再工作了。
有人可以告诉我,如果我错过了某个地方的同步吗?我如何添加它?我没有在这里复制整个代码,因为它会是大量的代码 :D Vulkan 非常 codddddddddy。但是,如果您需要一些安静的代码,请提出要求,我可以将其粘贴在这里。
期间我做了什么:
- 重建 vulkan 的整个初始化代码(现在我使用 .hpp 而不是 .h,这导致在编译时进行一些很好的类型检查)
- 一切,每一行都手工打一遍(没有复制粘贴),问题依旧
- 光栅渲染我已经注释掉了->没问题(但是问题出现在acquireNextImage和present,所以我需要光栅渲染才能解决问题)
- 如果我注释掉加速结构的搭建->没问题
- 如果我在 (!) 构建 acc 结构之后放置一个断点,但在同步区域(此时光栅化器不能 运行,必须在 CPU 端等待)->没问题
我的结论:我错过了构建 Acc 结构和光栅化之间的一些同步。不知道哪里漏了,因为我用的不一样:
- 队列族(光栅化器使用图形队列族 0,acc 结构计算队列族 1)
- 不同的信号量(acc 生成器和光栅器有自己的信号量和栅栏)
- 我还没有使用 acc 缓冲区,我只是创建它。
我不知道,那里发生了什么。为什么一切都很好,如果我用断点暂停?因为,如果一个参数是错误的,我应该在断点上遇到同样的问题,不是吗?所以我的理解是,同步有问题。但问题是,acquireNextImage 因 DeviceLost 错误而失败。这可能是一个错误的参数,超出范围的指针等
我要深入调查...^^
我找到问题了!这是正确的提示和接缝,与我的问题相同:
https://www.reddit.com/r/vulkan/comments/fqu90h/submitting_command_buffer_to_compute_queue_for/
所以我没有为我的加速缓冲区分配内存,这里是:
- == bottom acceleration structure ==
- get acceleration structure build sizes info
- create buffer (acceleration structure storage, shader device address) <---- no memory
在我注意到 reddit 上的 post 之前,我已经为我的暂存缓冲区分配了内存,因为我认为它是必需的,因为我从中获取了设备地址。但是在 Web 的某个地方我读到了加速结构缓冲区,它不需要任何内存分配并且这是在幕后完成的。但事实并非如此:)
所以现在我的代码可以工作了,我现在可以继续学习和构建顶级加速结构了:)
我想弄明白,如何使用光线追踪。我所拥有的是一个光栅化器绘制的三角形(与 Vulkan 教程中显示的大部分相同,但重构为我自己的代码和实用程序函数)。由于 window resizing/minimizing 等原因,交换链的重建工作正常。
然后我添加了底部加速结构的创建。从那以后,我遇到了一些“设备丢失”错误,但并非总是如此……这是我的代码框架:
mainLoop:
- acquireNextImage
- renderWorld
- render gui
- present
acquireNextImage:
- signaling a semaphore "Image Available"
render gui:
- wait for fence "Gui"
- begin command buffer (use graphics queue)
- begin render pass
- bind pipeline (graphics)
- set viewport
- set scissor
- draw (2 triangles in my GUI yet)
- end render pass
- end command buffer
- reset fence "Gui"
- submit command buffer (waiting for semaphore "Image Available", signaling semaphore "Rendering Done", checking fence "Gui")
present:
- queue present (waiting for semaphore "Rendering Done")
renderWorld:
(actually this does not render anything yet, it just creates a vertex buffer, an index buffer, and creates the bottom acceleration strucutre for it - and caches it for further frames, so this code runs only once at start!)
- == vertexbuffer ==
- create buffer (usage transfer dst)
- get buffer memory requirements
- allocate memory (device local)
- bind buffer memory
- create buffer (usage transfer src) (this is my staging buffer)
- get buffer memory requirements
- allocate memory (host visible, host coherent) (this is my staging memory)
- bind buffer memory
- wait for fence "Transfer"
- begin command buffer (use dedicated transfer queue)
- copy buffer
- end command buffer
- reset fence "Transfer"
- submit command buffer (checking fence "Transfer")
- wait queue idle
- free stating memory
- destroy staging buffer
- == indexbuffer ==
- create buffer (usage transfer dst)
- get buffer memory requirements
- allocate memory (device local)
- bind buffer memory
- create buffer (usage transfer src) (this is my staging buffer)
- get buffer memory requirements
- allocate memory (host visible, host coherent) (this is my staging memory)
- bind buffer memory
- wait for fence "Transfer"
- begin command buffer (use dedicated transfer queue)
- copy buffer
- end command buffer
- reset fence "Transfer"
- submit command buffer (checking fence "Transfer")
- wait queue idle
- free stating memory
- destroy staging buffer
- == bottom acceleration structure ==
- get acceleration structure build sizes info
- create buffer (acceleration structure storage, shader device address)
- create acceleration structure (bottom level)
- create buffer (acceleration structure storage, shader device address) (this is my scratch buffer)
- wait for fence "BuildAcc"
- begin command buffer (use dedicated compute queue)
- pipeline barrier (transfer write -> acceleration structure write), don't know if I need it here
- build acceleration structures
- pipeline barrier (acceleration structure write -> shader read), don't know if I need it here
- end command buffer
- reset fence "BuildAcc"
- submit command buffer (checking fence "BuildAcc")
- wait queue idle <------- here device lost
- destroy scratch buffer
所以,如果我注释掉“renderWorld”,一切正常。如果我让 renderWorld 进入,那么我会丢失一个设备(请参阅最后的“等待队列空闲”行)。但不是每次我运行程序。
如果我在“wait queue idle”这一行下了一个断点,当程序停在这一行后,我可以继续执行程序,一切都很好。另外,如果我注释掉“build acceleration structures”命令,一切正常(当然除了没有 acc 结构,但没有设备丢失)。
所以我不知道,问题出在哪里。在我看来,我需要以某种方式同步一些东西,因为有了断点我可以 运行 它并且它可以工作。所以我理解的代码一定没问题。
除了缺少着色器绑定外,也没有验证错误,但因为我还没有使用它们(我还没有光线追踪渲染),我应该不是问题。
设备丢失后,其他信号量没有重置,我的 gui 渲染路径也不再工作了。
有人可以告诉我,如果我错过了某个地方的同步吗?我如何添加它?我没有在这里复制整个代码,因为它会是大量的代码 :D Vulkan 非常 codddddddddy。但是,如果您需要一些安静的代码,请提出要求,我可以将其粘贴在这里。
期间我做了什么:
- 重建 vulkan 的整个初始化代码(现在我使用 .hpp 而不是 .h,这导致在编译时进行一些很好的类型检查)
- 一切,每一行都手工打一遍(没有复制粘贴),问题依旧
- 光栅渲染我已经注释掉了->没问题(但是问题出现在acquireNextImage和present,所以我需要光栅渲染才能解决问题)
- 如果我注释掉加速结构的搭建->没问题
- 如果我在 (!) 构建 acc 结构之后放置一个断点,但在同步区域(此时光栅化器不能 运行,必须在 CPU 端等待)->没问题
我的结论:我错过了构建 Acc 结构和光栅化之间的一些同步。不知道哪里漏了,因为我用的不一样:
- 队列族(光栅化器使用图形队列族 0,acc 结构计算队列族 1)
- 不同的信号量(acc 生成器和光栅器有自己的信号量和栅栏)
- 我还没有使用 acc 缓冲区,我只是创建它。
我不知道,那里发生了什么。为什么一切都很好,如果我用断点暂停?因为,如果一个参数是错误的,我应该在断点上遇到同样的问题,不是吗?所以我的理解是,同步有问题。但问题是,acquireNextImage 因 DeviceLost 错误而失败。这可能是一个错误的参数,超出范围的指针等
我要深入调查...^^
我找到问题了!这是正确的提示和接缝,与我的问题相同:
https://www.reddit.com/r/vulkan/comments/fqu90h/submitting_command_buffer_to_compute_queue_for/
所以我没有为我的加速缓冲区分配内存,这里是:
- == bottom acceleration structure ==
- get acceleration structure build sizes info
- create buffer (acceleration structure storage, shader device address) <---- no memory
在我注意到 reddit 上的 post 之前,我已经为我的暂存缓冲区分配了内存,因为我认为它是必需的,因为我从中获取了设备地址。但是在 Web 的某个地方我读到了加速结构缓冲区,它不需要任何内存分配并且这是在幕后完成的。但事实并非如此:)
所以现在我的代码可以工作了,我现在可以继续学习和构建顶级加速结构了:)