线程在VkFence未提交前等待引发验证错误,用法是否合规?
问题场景
你在实现异步VkCommandBuffer录制优化资源加载时,遇到以下验证错误:
UNASSIGNED-Threading-MultipleThreads(ERROR / SPEC): msgNum: 337425955 - Validation Error: [ UNASSIGNED-Threading-MultipleThreads ] Object 0: handle = 0x90a67000000088d3, type = VK_OBJECT_TYPE_FENCE; | MessageID = 0x141cb623 | THREADING ERROR : vkQueueSubmit(): object of type VkFence is simultaneously used in thread 0x3344 and thread 0x2d3c
当gSubmitBeforeWaitFence设为false时,工作线程会在主线程提交VkFence前就调用vkWaitForFences,触发上述错误;设为true则正常运行。
结论:这是你的用法错误,验证层的报错符合规范
规范依据
Vulkan核心规范的6.5. 同步对象的线程安全章节明确规定:所有对同步对象(包括Fence、Semaphore、Event)的操作,都必须通过外部同步机制保证不会有两个线程同时操作同一个对象,除非该操作被明确标记为线程安全。
vkQueueSubmit关联Fence的操作、vkWaitForFences操作都不属于规范允许无外部同步的范畴——哪怕你认为vkWaitForFences是“只读”操作,Vulkan依然要求你确保同一时间只有一个线程对该Fence执行任何操作。
错误原因
当gSubmitBeforeWaitFence为false时,工作线程调用vkWaitForFences和主线程调用vkQueueSubmit(会将Fence设置为未触发状态)的操作同时发生,且没有任何外部同步机制(比如互斥锁),完全违反了同步对象的线程安全要求,因此验证层的报错是正确的。
修复方案
- 优先采用你已经验证有效的方式:确保主线程调用
vkQueueSubmit关联Fence之后,工作线程再启动vkWaitForFences(即gSubmitBeforeWaitFence=true的逻辑); - 如果需要更灵活的线程调度,可通过互斥锁、条件变量等外部同步手段,保证同一时间只有一个线程对目标Fence执行操作;
- 异步资源加载的标准流程通常是:主线程提交命令缓冲并关联Fence → 工作线程等待Fence触发 → 完成后进行资源的后续处理,这种天然的顺序性可以从根源上避免线程冲突。
内容的提问来源于stack exchange,提问作者Siliace

