Files
XCEngine/docs/api/XCEngine/RHI/RHIFence/RHIFence.md
2026-03-29 01:36:53 +08:00

3.2 KiB
Raw Blame History

RHIFence

命名空间: XCEngine::RHI

类型: class (abstract)

头文件: XCEngine/RHI/RHIFence.h

描述: GPU 同步原语接口,用于 signal、wait 和 completed value 查询,是命令队列同步和 frame pacing 的基础构件。

角色概述

RHIFence 是当前 RHI 抽象层里最基础的同步对象。它通常和 RHICommandQueue 配合使用,用来表达:

  • 某个 GPU 提交点是否已经完成
  • CPU 是否需要等待某个值
  • 当前完成值推进到了哪里

如果拿商用引擎常见心智模型来理解,它更接近 timeline-style fence / completion fence而不是图形 API 中所有同步原语的统一抽象。

当前接口

一个必须写清楚的细节:无参 Signal() 并不完全统一

RHIFence 同时提供:

  • Signal()
  • Signal(uint64_t value)

但当前无参重载在不同后端上的实现并不完全一致:

  • D3D12 当前实现等价于 Signal(1)
  • OpenGL 当前实现也等价于 Signal(1)
  • Vulkan 当前头文件实现是 ++m_value

这意味着:

  • 无参 Signal() 不是跨后端严格统一的 timeline 递增语义
  • 如果你需要可移植、可推断的同步值行为,应该优先使用显式值重载 Signal(value)

这是一个非常值得文档明确指出的实现事实。

Wait() 和 completed value 语义

当前测试已经覆盖:

  • signal 到某个值后 wait
  • completed value 递增到更大值
  • wait 一个小于已完成值的目标
  • 多次 signal / wait 组合

从这些测试和当前实现看,更合理的理解是:

  • Wait(value) 表示“至少等到这个值”
  • GetCompletedValue() 返回当前后端已完成的最大同步值

RHICommandQueue 的关系

有两条常见用法:

fence 自己 signal / wait

测试里直接调用:

  • fence->Signal(value)
  • fence->Wait(value)

由 queue 推进 fence

队列也有:

  • queue->Signal(fence, value)
  • queue->Wait(fence, value)

这更接近真实 GPU 提交流程中的使用方式。

当前设计边界

RHIFence 当前没有提供:

  • 多对象 join / fan-in 抽象
  • semaphore 风格资源依赖表达
  • timeline semaphore / binary semaphore 的统一细分类型

它的定位就是一层简单、可验证的 completion fence。

native handle 语义

GetNativeHandle() 也是明显的后端逃逸口:

  • D3D12 下是原生 fence 对象
  • OpenGL 下是 GLsync
  • Vulkan 当前 public 实现甚至可能返回 nullptr

因此调用方不能把它当成稳定跨后端能力。

生命周期

RHIFenceRHIDevice 创建,并以裸指针返回。使用完成后推荐:

  1. Shutdown
  2. delete

相关文档