diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Constructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Constructor.md index a6a50b86..0c2cd415 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Constructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Constructor.md @@ -1,4 +1,4 @@ -# OpenGLFence::OpenGLFence +# OpenGLFence::OpenGLFence() ```cpp OpenGLFence(); @@ -6,13 +6,19 @@ OpenGLFence(); ## 作用 -构造一个空 fence 对象。 +构造一个尚未创建 `GLsync` 的 OpenGL fence 对象。 ## 当前实现行为 -- 不创建 `GLsync`。 -- `m_signaledValue` 与 `m_completedValue` 初始化为 `0`。 +- 把 `m_sync` 置为 `nullptr` +- 把 `m_signaledValue` 和 `m_completedValue` 初始化为 `0` +- 不创建 OpenGL 同步对象 + +## 设计说明 + +当前类采用的是“懒创建同步对象”的思路。只有在 [Signal](Signal.md) 或 [GetNativeHandle](GetNativeHandle.md) 真正需要同步句柄时,才会插入 `glFenceSync`。 ## 相关文档 - [Initialize](Initialize.md) +- [Signal](Signal.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Destructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Destructor.md index dfc4a603..f35f23fa 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Destructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Destructor.md @@ -1,4 +1,4 @@ -# OpenGLFence::~OpenGLFence +# OpenGLFence::~OpenGLFence() ```cpp ~OpenGLFence() override; @@ -6,13 +6,13 @@ ## 作用 -销毁 fence 并释放内部 `GLsync`。 +析构 fence 对象并释放当前仍然持有的同步句柄。 ## 当前实现行为 -- 析构函数调用 [`Shutdown`](Shutdown.md)。 -- 如果内部仍持有 sync,会执行 `glDeleteSync()`。 +- 析构函数直接调用 [Shutdown](Shutdown.md) ## 相关文档 - [Shutdown](Shutdown.md) +- [OpenGLFence](OpenGLFence.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetCompletedValue.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetCompletedValue.md index c0eecff7..d5a1fcd7 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetCompletedValue.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetCompletedValue.md @@ -1,4 +1,4 @@ -# OpenGLFence::GetCompletedValue +# OpenGLFence::GetCompletedValue() ```cpp uint64_t GetCompletedValue() const override; @@ -6,19 +6,26 @@ uint64_t GetCompletedValue() const override; ## 作用 -查询 fence 当前已完成到哪个值。 - -## 返回值 - -- 如果没有活动中的 `GLsync`,返回 `m_completedValue`。 -- 如果 `GLsync` 已被驱动标记为 `GL_SIGNALED`,返回 `m_signaledValue`。 -- 否则返回 `m_completedValue`。 +查询当前 fence 已完成到哪个值。 ## 当前实现行为 -- 该函数会查询 `GL_SYNC_STATUS`,但不会主动删除 sync,也不会把 `m_completedValue` 写回最新值。 +- 如果 `m_sync == nullptr`,直接返回 `m_completedValue` +- 否则调用 `glGetSynciv(..., GL_SYNC_STATUS, ...)` 读取同步对象状态 +- 当状态为 `GL_SIGNALED` 时,返回 `m_signaledValue` +- 当状态仍未完成时,返回 `m_completedValue` + +## 需要特别注意 + +- 这个方法不会在 `GL_SIGNALED` 时自动更新 `m_completedValue` +- 也不会删除当前 `m_sync` +- 因为当前实现不强制值单调递增,所以返回值理论上也可能比历史更小 + +## 设计说明 + +这体现了当前类的本质: 它只是用一个 `GLsync` 加两份 CPU 侧原子计数去“近似” timeline fence 接口,而不是严格复刻显式 API 的时间线语义。 ## 相关文档 -- [Wait](Wait.md) - [Signal](Signal.md) +- [Wait](Wait.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetNativeHandle.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetNativeHandle.md index 4cd3f8ea..927feb37 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetNativeHandle.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/GetNativeHandle.md @@ -1,4 +1,4 @@ -# OpenGLFence::GetNativeHandle +# OpenGLFence::GetNativeHandle() ```cpp void* GetNativeHandle() override; @@ -6,17 +6,20 @@ void* GetNativeHandle() override; ## 作用 -返回底层 `GLsync` 句柄。 - -## 返回值 - -- 返回内部 `GLsync`,以 `void*` 形式暴露。 +返回底层 OpenGL 同步句柄。 ## 当前实现行为 -- 如果当前还没有 sync,会立即调用 `glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)` 创建一个新的。 -- 因此它不是纯 getter,而是带副作用的懒初始化接口。 +- 如果当前 `m_sync == nullptr`,会立刻执行 `glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)` 创建一个新的同步对象 +- 返回 `m_sync` + +## 需要特别注意 + +- 这个方法有副作用,不是纯查询接口 +- 它不会同步更新 `m_signaledValue` 或 `m_completedValue` +- 因此“拿 native handle”本身就可能额外插入一段新的 GPU 栅栏 ## 相关文档 - [Signal](Signal.md) +- [GetCompletedValue](GetCompletedValue.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Initialize.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Initialize.md index a82ff186..942ac1da 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Initialize.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Initialize.md @@ -1,4 +1,4 @@ -# OpenGLFence::Initialize +# OpenGLFence::Initialize() ```cpp bool Initialize(uint64_t initialValue = 0); @@ -6,22 +6,29 @@ bool Initialize(uint64_t initialValue = 0); ## 作用 -初始化 CPU 侧 fence 计数状态。 +初始化 fence 的 CPU 侧计数状态。 ## 参数 -- `initialValue`: 初始 signaled / completed 值。 +- `initialValue`: 初始 signal/completed 值 ## 返回值 -- 当前实现始终返回 `true`。 +`bool`。当前实现始终返回 `true`。 ## 当前实现行为 -- 不会立即创建 `GLsync`。 -- 仅把 `m_signaledValue` 和 `m_completedValue` 设为 `initialValue`。 +- 把 `m_signaledValue` 设置为 `initialValue` +- 把 `m_completedValue` 设置为 `initialValue` +- 不创建 `GLsync` +- 不执行任何 OpenGL 同步调用 + +## 需要特别注意 + +直接调用这个方法时,`initialValue` 会被完整保留;但如果走 `OpenGLDevice::CreateFence(const FenceDesc&)`,当前设备实现传入的是 `desc.initialValue > 0`,所以任何正值都会被折叠成 `1`。 ## 相关文档 - [Signal](Signal.md) -- [GetCompletedValue](GetCompletedValue.md) +- [Wait](Wait.md) +- [OpenGLFence](OpenGLFence.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/OpenGLFence.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/OpenGLFence.md index 6ce2b61f..cb8b53ee 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/OpenGLFence.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/OpenGLFence.md @@ -6,46 +6,64 @@ **头文件**: `XCEngine/RHI/OpenGL/OpenGLFence.h` -**描述**: OpenGL 后端的同步对象封装,使用单个 `GLsync` 配合 CPU 侧计数值模拟 timeline 风格的 fence 接口。 +**描述**: OpenGL 后端的同步对象封装,使用单个 `GLsync` 和两份 CPU 侧原子计数,近似实现 `RHIFence` 的 timeline 风格接口。 -## 概述 +## 概览 -OpenGL 没有 D3D12 那种原生 timeline fence 接口,更多是一次性的 `GLsync` 栅栏。`OpenGLFence` 的实现方式,是把: +OpenGL 原生提供的是一次性的 `GLsync` 栅栏,而不是 D3D12/Vulkan 那种严格单调、可长期复用的 timeline fence。`OpenGLFence` 的实现思路是: -- 一个可被替换的 `GLsync` -- 一个“最近 signal 的值” -- 一个“最近确认完成的值” +- GPU 侧只保留一个当前有效的 `GLsync` +- CPU 侧记录“最近一次 signal 的值” +- 再记录“最近一次确认完成的值” -组合起来,向 RHI 暴露出近似 timeline fence 的 API 形状。 - -这类适配在跨后端引擎里很常见,但要明确一点: 它的接口看起来像 timeline fence,不代表底层语义真的和 D3D12 / Vulkan 完全一致。 +这样做可以让跨后端 RHI 保持统一的 `Signal(value)` / `Wait(value)` / `GetCompletedValue()` 接口形状,但底层语义仍然是 OpenGL 风格的单栅栏模型。 ## 当前实现的真实行为 -- 对象内部同一时间只维护一个 `GLsync`。 -- 每次 [`Signal`](Signal.md) 新值时,如果旧 `GLsync` 还存在,会先等待并删除旧同步对象。 -- [`Wait`](Wait.md) 等待成功后,会把 `m_completedValue` 直接更新为当前 `m_signaledValue`。 -- [`GetNativeHandle`](GetNativeHandle.md) 在还没有 sync 时会懒创建一个新的 `GLsync`。 +- 同一时间只维护一个 `GLsync` +- [Initialize](Initialize.md) 只设置计数值,不创建同步对象 +- [Signal](Signal.md) 新值时,如果旧 `GLsync` 还在,会先等待并删除旧栅栏 +- `Signal(value)` 会先 `glFlush()`,再插入新的 `glFenceSync` +- [Wait](Wait.md) 成功等待后,会把 `m_completedValue` 直接写成当前 `m_signaledValue` +- [GetCompletedValue](GetCompletedValue.md) 只做轮询,不会在查询时清理同步对象 +- [GetNativeHandle](GetNativeHandle.md) 是懒创建接口,本身可能新增一段栅栏 +- `Signal()` 的无参重载并不是“递增 1”,而是固定转发为 `Signal(1)` -## 设计取舍 +## 设计背景 -- 这种实现足够支撑当前引擎的基础“提交后等待完成”流程。 -- 代价是它不能同时保留多段独立的 in-flight timeline 历史。 +商业级引擎在 OpenGL 后端里,通常都会做这类“接口现代化,底层实现务实化”的适配。原因很简单: -## 当前限制 +- 上层系统希望用统一的 fence API 驱动命令队列、截图、测试和提交流程 +- OpenGL 没有真正的 timeline fence,可选方案本来就有限 +- 单个 `GLsync` 包装器已经足够覆盖当前引擎里最常见的“提交后等待完成”需求 -- 不是严格意义上的 timeline fence。 -- 如果通过 [`OpenGLDevice::CreateFence`](../OpenGLDevice/CreateFence.md) 创建,`initialValue > 0` 当前只会被折叠成 `1`,不会保留原始数值。 -- `GetNativeHandle()` 本身带有副作用: 可能会额外插入新的 `GLsync`。 +换句话说,当前类的目标不是完美模拟显式 API,而是把 OpenGL 的同步原语整理成对引擎友好的形式。 -## 重点方法 +## 生命周期 + +- [OpenGLFence()](Constructor.md) 初始化为空状态 +- [Initialize](Initialize.md) 设置起始计数 +- [Signal](Signal.md) 插入新的 GPU 栅栏并记录 signal 值 +- [Wait](Wait.md) 在 CPU 侧等待当前栅栏完成 +- [Shutdown](Shutdown.md) 删除同步对象并清零计数 + +## 重要限制 + +- 不是严格意义上的 timeline fence +- 不保证值单调递增 +- 不保留多段 in-flight 历史,只关注“当前这一个 sync” +- `GetNativeHandle()` 有副作用 +- 通过 `OpenGLDevice::CreateFence(...)` 创建时,`initialValue > 0` 会被折叠成 `1` + +## 关键方法 - [Initialize](Initialize.md) - [Signal](Signal.md) - [Wait](Wait.md) - [GetCompletedValue](GetCompletedValue.md) +- [GetNativeHandle](GetNativeHandle.md) ## 相关文档 -- [OpenGL](../OpenGL.md) - [OpenGLCommandQueue](../OpenGLCommandQueue/OpenGLCommandQueue.md) +- [OpenGLDevice](../OpenGLDevice/OpenGLDevice.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Shutdown.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Shutdown.md index d91093f6..2956c25d 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Shutdown.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Shutdown.md @@ -1,4 +1,4 @@ -# OpenGLFence::Shutdown +# OpenGLFence::Shutdown() ```cpp void Shutdown() override; @@ -6,13 +6,20 @@ void Shutdown() override; ## 作用 -释放内部同步对象并重置计数状态。 +释放当前同步对象,并把 fence 状态重置为初始值。 ## 当前实现行为 -- 如果 `m_sync` 存在,则调用 `glDeleteSync()` 并清空指针。 -- 把 `m_signaledValue` 和 `m_completedValue` 都重置为 `0`。 +- 如果 `m_sync` 非空,则调用 `glDeleteSync` +- 把 `m_sync` 置为 `nullptr` +- 把 `m_signaledValue` 置为 `0` +- 把 `m_completedValue` 置为 `0` + +## 设计说明 + +由于当前类只拥有一个 `GLsync`,`Shutdown()` 的职责非常直接,就是删除它并清空 CPU 侧状态。 ## 相关文档 - [Destructor](Destructor.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Signal.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Signal.md index 8f63b6ce..b82a0678 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Signal.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Signal.md @@ -1,4 +1,4 @@ -# OpenGLFence::Signal +# OpenGLFence::Signal() ```cpp void Signal() override; @@ -7,19 +7,41 @@ void Signal(uint64_t value) override; ## 作用 -插入一条新的 OpenGL 同步点,并记录对应的 fence 值。 +为当前 fence 记录一个新的 signal 点,并插入新的 GPU 栅栏。 -## 当前实现行为 +## 无参重载 -- 无参版本等价于 `Signal(1)`。 -- 如果旧 `GLsync` 还存在,会先等待它完成并删除,再创建新的 `GLsync`。 -- 在创建新 sync 前会先调用 `glFlush()`。 -- `m_signaledValue` 被更新为传入值。 +```cpp +void Signal() override; +``` -## 当前限制 +### 当前实现行为 -- 不强制值单调递增。 -- 因为旧 sync 会被替换,它不能保留多段未完成 timeline 的历史。 +- 直接转发到 `Signal(1)` + +### 需要特别注意 + +这不是“在当前值基础上递增 1”,而是固定把 signal 值设置为 `1`。 + +## 带值重载 + +```cpp +void Signal(uint64_t value) override; +``` + +### 当前实现行为 + +- 如果已有旧 `m_sync`: + - 先 `glClientWaitSync(..., GL_TIMEOUT_IGNORED)` + - 再 `glDeleteSync` + - 然后把 `m_sync` 置空 +- 调用 `glFlush()` +- 把 `m_signaledValue` 更新为 `value` +- 调用 `glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)` 创建新的同步对象 + +## 设计说明 + +这套实现的本质是“用最新的一次 signal 覆盖上一段历史”。它适合当前引擎的基础提交模型,但和真正能保留完整时间线历史的 fence 仍然不同。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Wait.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Wait.md index b4f9bb48..94714b91 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Wait.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLFence/Wait.md @@ -1,4 +1,4 @@ -# OpenGLFence::Wait +# OpenGLFence::Wait() ```cpp void Wait(uint64_t value) override; @@ -6,22 +6,28 @@ void Wait(uint64_t value) override; ## 作用 -在 CPU 侧等待 fence 达到指定值。 - -## 参数 - -- `value`: 希望等待到的 fence 值。 +等待 fence 至少达到给定值。 ## 当前实现行为 -- 如果 `m_completedValue >= value`,直接返回。 -- 如果内部存在 `GLsync`,会调用 `glClientWaitSync(..., GL_TIMEOUT_IGNORED)` 阻塞等待,然后删除该 sync。 -- 等待结束后,把 `m_completedValue` 更新为当前 `m_signaledValue`。 +- 先读取 `m_completedValue` +- 如果 `m_completedValue >= value`,直接返回 +- 否则如果 `m_sync` 存在: + - 调用 `glClientWaitSync(..., GL_TIMEOUT_IGNORED)` + - 删除当前 `m_sync` + - 把 `m_sync` 置为 `nullptr` +- 最后读取 `m_signaledValue` +- 把 `m_completedValue` 直接设置为该 `m_signaledValue` -## 当前限制 +## 需要特别注意 -- 它并不会验证“当前 signaled 值是否真的大于等于请求值”。 -- 这再次说明它是“单 sync + 计数缓存”的模拟方案,而不是真 timeline fence。 +- 这里写回的是“当前最近 signal 的值”,不是传入的 `value` +- 因此 `Wait(3)` 在最近一次 signal 是 `5` 时,会把 completed 推到 `5` +- 反过来,如果之后又 `Signal(3)`,那么新的等待结果也可能把 completed 从更大的历史值降回 `3` + +## 设计说明 + +这再次说明当前类不维护严格单调 timeline。它只是在单个 `GLsync` 完成后,把“最近一次 signal 值”认定为已完成。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Constructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Constructor.md index 159c015b..f900559a 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Constructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Constructor.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::OpenGLPipelineLayout +# OpenGLPipelineLayout::OpenGLPipelineLayout() ```cpp OpenGLPipelineLayout() = default; @@ -6,14 +6,21 @@ OpenGLPipelineLayout() = default; ## 作用 -构造一个空的 pipeline layout 元数据对象。 +构造一个尚未初始化的 pipeline layout 适配对象。 ## 当前实现行为 -- 使用编译器默认构造。 -- 不会自动初始化映射表。 -- 真正的布局复制与 binding point 计算发生在 [`Initialize`](Initialize.md)。 +- 使用编译器生成的默认构造函数 +- 依赖成员默认值: + - `m_desc = {}` + - `m_initialized = false` + - 各个映射与缓存容器为空 + +## 设计说明 + +这是一个纯 CPU 侧元数据对象,不对应 OpenGL 驱动里的原生 layout 句柄,因此构造阶段不需要做额外 API 调用。 ## 相关文档 - [Initialize](Initialize.md) +- [UsesSetLayouts](UsesSetLayouts.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Destructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Destructor.md index 9c671928..ef2b6cf5 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Destructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Destructor.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::~OpenGLPipelineLayout +# OpenGLPipelineLayout::~OpenGLPipelineLayout() ```cpp ~OpenGLPipelineLayout() override = default; @@ -6,14 +6,19 @@ ## 作用 -销毁对象。 +析构 pipeline layout 对象。 ## 当前实现行为 -- 依赖成员对象自身析构释放 CPU 侧容器。 -- 不会显式调用 [`Shutdown`](Shutdown.md)。 -- 因为它不持有 OpenGL 驱动对象,这种默认析构方式是可行的。 +- 使用默认析构函数 +- 由成员容器自动释放 CPU 侧缓存 +- 不会主动调用 [Shutdown](Shutdown.md) + +## 设计说明 + +由于当前类只管理 CPU 内存,没有 OpenGL 原生资源,默认析构已经足够完成清理。 ## 相关文档 - [Shutdown](Shutdown.md) +- [OpenGLPipelineLayout](OpenGLPipelineLayout.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetConstantBufferBindingPoint.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetConstantBufferBindingPoint.md index b50fdae8..2d007949 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetConstantBufferBindingPoint.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetConstantBufferBindingPoint.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetConstantBufferBindingPoint +# OpenGLPipelineLayout::GetConstantBufferBindingPoint() ```cpp uint32_t GetConstantBufferBindingPoint(uint32_t setIndex, uint32_t binding) const; @@ -6,19 +6,19 @@ uint32_t GetConstantBufferBindingPoint(uint32_t setIndex, uint32_t binding) cons ## 作用 -查询某个常量缓冲 binding 在 OpenGL 中应使用的实际 binding point。 - -## 返回值 - -- set-aware 模式下返回映射后的连续 binding point。 -- flat 模式下,如果 `setIndex == 0`,直接返回 `binding`。 -- 找不到映射时返回 `UINT32_MAX`。 +查询常量缓冲绑定在 OpenGL 里的实际 binding point。 ## 当前实现行为 -- 不同 set 会被映射到不同的全局 binding point,即使它们声明了相同的 binding 编号。 +- 在 set-aware 模式下: + - 若 `setIndex` 越界,返回 `UINT32_MAX` + - 若对应映射表里找不到 `binding`,返回 `UINT32_MAX` + - 否则返回预计算得到的 UBO binding point +- 在 flat 模式下: + - 仅当 `setIndex == 0` 时直接返回 `binding` + - 否则返回 `UINT32_MAX` ## 相关文档 - [HasConstantBufferBinding](HasConstantBufferBinding.md) -- [OpenGLDescriptorSet::BindWithPipelineLayout](../OpenGLDescriptorSet/BindWithPipelineLayout.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetDesc.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetDesc.md index 18a08277..8c54481a 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetDesc.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetDesc.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetDesc +# OpenGLPipelineLayout::GetDesc() ```cpp const RHIPipelineLayoutDesc& GetDesc() const; @@ -6,19 +6,19 @@ const RHIPipelineLayoutDesc& GetDesc() const; ## 作用 -返回内部保存的、已经过后端归一化处理的 pipeline layout 描述。 - -## 返回值 - -- 返回对内部 `m_desc` 的常量引用。 +返回当前对象内部保存的 layout 描述。 ## 当前实现行为 -- 在 set-aware 模式下,`setLayouts` 指向的是内部深拷贝后的数组。 -- `constantBufferCount`、`textureCount`、`uavCount`、`samplerCount` 也可能是重新累计后的值。 -- 调用 [`Shutdown`](Shutdown.md) 后,这个引用不再可用。 +- 直接返回 `m_desc` 的常量引用 + +## 需要特别注意 + +- 在 set-aware 模式下,`m_desc.setLayouts` 指向对象内部深拷贝后的布局数组 +- 在 flat 模式下,`m_desc` 只是对传入描述的浅拷贝 +- 调用 [Shutdown](Shutdown.md) 后,这个引用语义会随内部数据被清空而失效 ## 相关文档 - [Initialize](Initialize.md) -- [GetSetLayoutCount](GetSetLayoutCount.md) +- [Shutdown](Shutdown.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetNativeHandle.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetNativeHandle.md index beab5132..1655254d 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetNativeHandle.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetNativeHandle.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetNativeHandle +# OpenGLPipelineLayout::GetNativeHandle() ```cpp void* GetNativeHandle() override; @@ -6,19 +6,18 @@ void* GetNativeHandle() override; ## 作用 -返回后端原生句柄。 - -## 返回值 - -- 已初始化时返回 `this`。 -- 未初始化时返回 `nullptr`。 +以统一句柄形式返回当前 layout 对象。 ## 当前实现行为 -- OpenGL 没有原生的 pipeline layout 对象,因此这里返回的并不是驱动句柄。 -- 这个接口主要用于维持跨后端统一的 RHI 形状。 +- 若 `m_initialized` 为真,返回 `this` +- 否则返回 `nullptr` + +## 设计说明 + +当前类没有真正的 OpenGL 原生 layout 句柄,所以 `native handle` 只是引擎内部对象地址,用于统一接口兼容。 ## 相关文档 - [Initialize](Initialize.md) -- [GetDesc](GetDesc.md) +- [UsesSetLayouts](UsesSetLayouts.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSamplerBindingPoint.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSamplerBindingPoint.md index cd147468..3e86dfce 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSamplerBindingPoint.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSamplerBindingPoint.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetSamplerBindingPoint +# OpenGLPipelineLayout::GetSamplerBindingPoint() ```cpp uint32_t GetSamplerBindingPoint(uint32_t setIndex, uint32_t binding) const; @@ -6,20 +6,15 @@ uint32_t GetSamplerBindingPoint(uint32_t setIndex, uint32_t binding) const; ## 作用 -查询 sampler binding 在 OpenGL sampler unit 空间中的实际编号。 - -## 返回值 - -- set-aware 模式下返回映射后的 sampler unit。 -- flat 模式下 `setIndex == 0` 时直接返回 `binding`。 -- 未命中时返回 `UINT32_MAX`。 +查询 sampler 描述符在 OpenGL 中对应的 sampler binding point。 ## 当前实现行为 -- sampler 的编号空间独立于 SRV / UAV。 -- 这让同一个 `binding = 0` 可以分别映射为 `texture unit 0`、`image unit 0`、`sampler unit 0`。 +- set-aware 模式下,从 `samplerBindingPoints` 映射表查找 +- flat 模式下,仅 `setIndex == 0` 时直接返回 `binding` +- 查找失败或 `setIndex` 越界时返回 `UINT32_MAX` ## 相关文档 - [HasSamplerBinding](HasSamplerBinding.md) -- [OpenGLDescriptorSet::BindWithPipelineLayout](../OpenGLDescriptorSet/BindWithPipelineLayout.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSetLayoutCount.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSetLayoutCount.md index 0173b501..12d14fa5 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSetLayoutCount.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetSetLayoutCount.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetSetLayoutCount +# OpenGLPipelineLayout::GetSetLayoutCount() ```cpp uint32_t GetSetLayoutCount() const; @@ -6,16 +6,15 @@ uint32_t GetSetLayoutCount() const; ## 作用 -返回当前保存的 set layout 数量。 - -## 返回值 - -- 返回内部 `m_desc.setLayoutCount`。 +返回当前描述中记录的 set layout 数量。 ## 当前实现行为 -- 在 flat 模式下通常为 `0`。 -- 在 set-aware 模式下,数量来自 `Initialize()` 深拷贝后的内部描述。 +- 直接返回 `m_desc.setLayoutCount` + +## 注意事项 + +在 set-aware 模式下,这通常等于内部深拷贝后的 layout 数量;在 flat 模式下,它可能是 `0`。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetShaderResourceBindingPoint.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetShaderResourceBindingPoint.md index f48d05b7..04886f76 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetShaderResourceBindingPoint.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetShaderResourceBindingPoint.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetShaderResourceBindingPoint +# OpenGLPipelineLayout::GetShaderResourceBindingPoint() ```cpp uint32_t GetShaderResourceBindingPoint(uint32_t setIndex, uint32_t binding) const; @@ -6,19 +6,15 @@ uint32_t GetShaderResourceBindingPoint(uint32_t setIndex, uint32_t binding) cons ## 作用 -查询采样纹理 binding 在 OpenGL texture unit 空间中的实际编号。 - -## 返回值 - -- set-aware 模式下返回内部计算出的连续 texture unit。 -- flat 模式下 `setIndex == 0` 时直接返回 `binding`。 -- 未命中时返回 `UINT32_MAX`。 +查询 SRV 在 OpenGL 中对应的纹理单元 binding point。 ## 当前实现行为 -- 该映射与 `CBV`、`UAV`、`Sampler` 的 binding point 计数器彼此独立。 +- set-aware 模式下,从 `shaderResourceBindingPoints` 映射表查找 +- flat 模式下,仅 `setIndex == 0` 时直接返回 `binding` +- 查找失败或 `setIndex` 越界时返回 `UINT32_MAX` ## 相关文档 - [HasShaderResourceBinding](HasShaderResourceBinding.md) -- [OpenGLDescriptorSet::BindWithPipelineLayout](../OpenGLDescriptorSet/BindWithPipelineLayout.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetUnorderedAccessBindingPoint.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetUnorderedAccessBindingPoint.md index 7fcf52a5..0aeec1bf 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetUnorderedAccessBindingPoint.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/GetUnorderedAccessBindingPoint.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::GetUnorderedAccessBindingPoint +# OpenGLPipelineLayout::GetUnorderedAccessBindingPoint() ```cpp uint32_t GetUnorderedAccessBindingPoint(uint32_t setIndex, uint32_t binding) const; @@ -6,19 +6,15 @@ uint32_t GetUnorderedAccessBindingPoint(uint32_t setIndex, uint32_t binding) con ## 作用 -查询 `UAV` / image binding 在 OpenGL image unit 空间中的实际编号。 - -## 返回值 - -- set-aware 模式下返回重排后的 image unit。 -- flat 模式下 `setIndex == 0` 时直接返回 `binding`。 -- 未命中时返回 `UINT32_MAX`。 +查询 UAV 在 OpenGL 中对应的 image unit binding point。 ## 当前实现行为 -- 当前只是做编号重映射,不涉及 image format、访问权限或 mip / layer 细节。 +- set-aware 模式下,从 `unorderedAccessBindingPoints` 映射表查找 +- flat 模式下,仅 `setIndex == 0` 时直接返回 `binding` +- 查找失败或 `setIndex` 越界时返回 `UINT32_MAX` ## 相关文档 - [HasUnorderedAccessBinding](HasUnorderedAccessBinding.md) -- [OpenGLDescriptorSet::BindWithPipelineLayout](../OpenGLDescriptorSet/BindWithPipelineLayout.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasConstantBufferBinding.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasConstantBufferBinding.md index 578e9d1d..d2ab1748 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasConstantBufferBinding.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasConstantBufferBinding.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::HasConstantBufferBinding +# OpenGLPipelineLayout::HasConstantBufferBinding() ```cpp bool HasConstantBufferBinding(uint32_t setIndex, uint32_t binding) const; @@ -6,22 +6,16 @@ bool HasConstantBufferBinding(uint32_t setIndex, uint32_t binding) const; ## 作用 -判断某个 set 中是否存在常量缓冲 binding 映射。 - -## 参数 - -- `setIndex`: 目标 set 索引。 -- `binding`: 目标 binding 编号。 - -## 返回值 - -- set-aware 模式下,只有映射表中真的存在该 binding 才返回 `true`。 -- flat 模式下,只要 `setIndex == 0` 就返回 `true`。 +判断某个 `set + binding` 是否存在常量缓冲绑定映射。 ## 当前实现行为 -- 在 flat 模式下并不会严格检查 `binding` 是否超出 count。 -- 这意味着它更像“当前模式是否允许按 binding 直接访问”,而不是严格的边界验证函数。 +- set-aware 模式下: + - `setIndex` 越界时返回 `false` + - 否则检查 `constantBufferBindingPoints` 中是否存在该 `binding` +- flat 模式下: + - 仅根据 `setIndex == 0` 返回 `true` 或 `false` + - 不会进一步验证 `binding` 是否越界 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasSamplerBinding.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasSamplerBinding.md index 81fbf917..b839f09c 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasSamplerBinding.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasSamplerBinding.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::HasSamplerBinding +# OpenGLPipelineLayout::HasSamplerBinding() ```cpp bool HasSamplerBinding(uint32_t setIndex, uint32_t binding) const; @@ -6,13 +6,14 @@ bool HasSamplerBinding(uint32_t setIndex, uint32_t binding) const; ## 作用 -判断某个 set 中是否存在 sampler binding 的映射。 +判断某个 `set + binding` 是否存在 sampler 绑定映射。 -## 返回值 +## 当前实现行为 -- set-aware 模式下按映射表判断。 -- flat 模式下,只要 `setIndex == 0` 就返回 `true`。 +- set-aware 模式下查询 `samplerBindingPoints` +- flat 模式下仅校验 `setIndex == 0` ## 相关文档 - [GetSamplerBindingPoint](GetSamplerBindingPoint.md) +- [UsesSetLayouts](UsesSetLayouts.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasShaderResourceBinding.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasShaderResourceBinding.md index 58d9981f..d0813f0d 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasShaderResourceBinding.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasShaderResourceBinding.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::HasShaderResourceBinding +# OpenGLPipelineLayout::HasShaderResourceBinding() ```cpp bool HasShaderResourceBinding(uint32_t setIndex, uint32_t binding) const; @@ -6,17 +6,14 @@ bool HasShaderResourceBinding(uint32_t setIndex, uint32_t binding) const; ## 作用 -判断某个 set 中是否存在采样纹理 binding 的映射。 - -## 返回值 - -- set-aware 模式下按映射表判断。 -- flat 模式下,只要 `setIndex == 0` 就返回 `true`。 +判断某个 `set + binding` 是否存在 SRV 绑定映射。 ## 当前实现行为 -- 与常量缓冲版本一样,flat 模式不会按 texture 数量做严格越界校验。 +- set-aware 模式下查询 `shaderResourceBindingPoints` +- flat 模式下仅校验 `setIndex == 0` ## 相关文档 - [GetShaderResourceBindingPoint](GetShaderResourceBindingPoint.md) +- [UsesSetLayouts](UsesSetLayouts.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasUnorderedAccessBinding.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasUnorderedAccessBinding.md index 42c4981a..4c86f74d 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasUnorderedAccessBinding.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/HasUnorderedAccessBinding.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::HasUnorderedAccessBinding +# OpenGLPipelineLayout::HasUnorderedAccessBinding() ```cpp bool HasUnorderedAccessBinding(uint32_t setIndex, uint32_t binding) const; @@ -6,13 +6,14 @@ bool HasUnorderedAccessBinding(uint32_t setIndex, uint32_t binding) const; ## 作用 -判断某个 set 中是否存在 `UAV` / image binding 的映射。 +判断某个 `set + binding` 是否存在 UAV 绑定映射。 -## 返回值 +## 当前实现行为 -- set-aware 模式下按映射表判断。 -- flat 模式下,只要 `setIndex == 0` 就返回 `true`。 +- set-aware 模式下查询 `unorderedAccessBindingPoints` +- flat 模式下仅校验 `setIndex == 0` ## 相关文档 - [GetUnorderedAccessBindingPoint](GetUnorderedAccessBindingPoint.md) +- [UsesSetLayouts](UsesSetLayouts.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Initialize.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Initialize.md index ab05ecde..3980d677 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Initialize.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Initialize.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::Initialize +# OpenGLPipelineLayout::Initialize() ```cpp bool Initialize(const RHIPipelineLayoutDesc& desc) override; @@ -6,29 +6,55 @@ bool Initialize(const RHIPipelineLayoutDesc& desc) override; ## 作用 -复制 pipeline layout 描述,并为 OpenGL 后端生成查询用的 binding point 映射。 - -## 参数 - -- `desc`: 通用 RHI 管线布局描述,可使用 count 方式,也可使用 `setLayouts` 方式。 +初始化 pipeline layout 元数据,并在需要时把 `set + binding` 映射压平成 OpenGL 的全局 binding point。 ## 返回值 -- 当前实现始终返回 `true`。 +`bool`。当前实现始终返回 `true`。 ## 当前实现行为 -- 先保存原始 `desc`,然后清空旧的映射和深拷贝缓存。 -- 如果提供了 `setLayouts`,会重新拷贝所有 set layout 并重新累计各类 descriptor 数量。 -- 对 `CBV`、`SRV`、`UAV`、`Sampler` 四类资源分别独立分配连续 binding point。 -- 映射顺序按 set 顺序遍历,set 内再按 binding 升序遍历。 -- 初始化完成后 `GetNativeHandle()` 会返回 `this`。 +- 先把传入的 `desc` 复制到 `m_desc` +- 清空: + - `m_setBindingPointMappings` + - `m_setLayouts` + - `m_setLayoutBindings` -## 失败与限制 +## 模式 1: set-aware -- 当前没有做参数合法性检查,例如重复 binding、空 binding 数组配合非零 count 等情况。 +当 `desc.setLayoutCount > 0 && desc.setLayouts != nullptr` 时进入该模式。 + +### 具体流程 + +- 把 `m_desc.constantBufferCount`、`textureCount`、`samplerCount`、`uavCount` 清零 +- 为每个 set 深拷贝 `DescriptorSetLayoutDesc` 和 `DescriptorSetLayoutBinding` 数组 +- 重新累计四类描述符总数 +- 让 `m_desc.setLayouts` 指向内部 `m_setLayouts` 缓存 +- 为每个 set 构建一份 `SetBindingPointMapping` +- 对每种 descriptor 类型分别维护独立的全局计数器: + - CBV + - SRV + - UAV + - Sampler +- 在每个 set 内,先按 `binding` 编号升序排序,再依次分配 binding point +- 分配后,计数器按 `binding.count` 递增;若 `count == 0`,则按 `1` 处理 + +## 模式 2: flat + +当没有 set layout 描述时: + +- 不生成 per-set 映射表 +- 保留 `m_desc = desc` 的浅拷贝结果 +- 后续 getter 会把 `setIndex == 0` 的 `binding` 直接当作实际 binding point 使用 + +## 设计说明 + +OpenGL 没有 Vulkan/D3D12 那种原生 pipeline layout,对应的资源绑定空间也是按类型分裂的全局空间。当前实现的价值就在于把更现代的 `set + binding` 组织方式,转译成 OpenGL 真正需要的编号系统。 ## 相关文档 - [UsesSetLayouts](UsesSetLayouts.md) -- [GetDesc](GetDesc.md) +- [GetConstantBufferBindingPoint](GetConstantBufferBindingPoint.md) +- [GetShaderResourceBindingPoint](GetShaderResourceBindingPoint.md) +- [GetUnorderedAccessBindingPoint](GetUnorderedAccessBindingPoint.md) +- [GetSamplerBindingPoint](GetSamplerBindingPoint.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/OpenGLPipelineLayout.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/OpenGLPipelineLayout.md index 8ecc009e..be2b0345 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/OpenGLPipelineLayout.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/OpenGLPipelineLayout.md @@ -6,63 +6,68 @@ **头文件**: `XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h` -**描述**: OpenGL 后端的 pipeline layout 适配对象,负责把 `set + binding` 关系重排成 OpenGL 的全局 binding point。 +**描述**: OpenGL 后端的 pipeline layout 适配对象,负责把现代 RHI 的 `set + binding` 资源布局翻译成 OpenGL 的全局 binding point。 -## 概述 +## 概览 -OpenGL 的 UBO、采样纹理、image、sampler 都共享各自的全局编号空间,而不是按 `descriptor set` 分组。`OpenGLPipelineLayout` 的存在价值,就是让引擎上层依然能写出更接近 Vulkan / D3D12 的资源布局,再由 OpenGL 后端把它们压平到各自的全局 binding space。 +OpenGL 不存在真正的原生 pipeline layout,也不会像 Vulkan 那样把不同资源先按 descriptor set 分组,再按 binding 解析。它更接近这种模型: -可以把它理解成一张“绑定点翻译表”: +- UBO 有自己的全局 binding 空间 +- 纹理采样单元有自己的全局 binding 空间 +- image unit 有自己的全局 binding 空间 +- sampler object 也依赖自己的编号体系 -- 上层看到的是 `setIndex + binding`。 -- OpenGL 真正需要的是 `uniform block binding`、`texture unit`、`image unit`、`sampler unit`。 +`OpenGLPipelineLayout` 的职责,就是把上层更现代的 `setIndex + binding` 描述,压平成这些 OpenGL 能直接消费的编号。 -这种做法的收益,是材质系统和命令列表代码不必为 OpenGL 退化成手写的裸 binding 规则。 +## 为什么要这样设计 -## 生命周期 +这是商业引擎里很典型的跨后端适配策略: -1. 由 [`OpenGLDevice::CreatePipelineLayout`](../OpenGLDevice/CreatePipelineLayout.md) 创建。 -2. [`Initialize`](Initialize.md) 复制 layout,并计算每个 set 的 binding point 映射。 -3. [`OpenGLDescriptorSet`](../OpenGLDescriptorSet/OpenGLDescriptorSet.md) 在 [`BindWithPipelineLayout`](../OpenGLDescriptorSet/BindWithPipelineLayout.md) 中查询这些映射。 -4. 销毁前可调用 [`Shutdown`](Shutdown.md) 清空 CPU 侧缓存。 +- 上层材质系统、命令列表、descriptor set 代码继续沿用统一的 set/binding 语义 +- OpenGL 后端把“不存在的原生 layout 对象”降级成一份 CPU 侧翻译表 +- 这样既保留了 API 设计的一致性,也避免了让整个引擎为了 OpenGL 倒退回裸 binding 编号风格 + +这类对象本质上不是 GPU 资源,而是“绑定规则元数据”。 ## 当前实现的真实行为 -### 两种工作模式 +- [Initialize](Initialize.md) 总是返回 `true` +- 存在两种工作模式: + - set-aware 模式 + - flat 模式 +- set-aware 模式下会深拷贝 set layout 和 binding 数组 +- 同一 descriptor 类型内部,binding point 会跨 set 全局递增 +- 映射分配前会按 binding 编号排序 +- `binding.count == 0` 时,当前算法仍会为其预留 `1` 个槽位 +- flat 模式下,只有 `setIndex == 0` 被视为有效 +- [GetNativeHandle](GetNativeHandle.md) 返回 `this` 或 `nullptr` -- 如果 `desc.setLayouts != nullptr` 且 `setLayoutCount > 0`,进入“set-aware”模式。 -- 否则进入“flat”模式。 +## 与其他模块的关系 -### set-aware 模式 +- [OpenGLDevice](../OpenGLDevice/OpenGLDevice.md) 通过 `CreatePipelineLayout(...)` 创建它 +- [OpenGLCommandList](../OpenGLCommandList/OpenGLCommandList.md) 在设置 graphics/compute descriptor set 时把它传下去 +- [OpenGLDescriptorSet](../OpenGLDescriptorSet/OpenGLDescriptorSet.md) 在 `BindWithPipelineLayout(...)` 中用它把逻辑 binding 解析成真正的 OpenGL binding point -- 会深拷贝所有 `DescriptorSetLayoutDesc` 和 `DescriptorSetLayoutBinding`。 -- 会重新累加 `constantBufferCount`、`textureCount`、`uavCount`、`samplerCount`。 -- 对每一种 descriptor 类型分别维护独立的连续 binding point 计数器。 -- 同一类型内部,按 binding 编号升序分配 binding point。 -- 不同 set 之间会继续递增,因此可以把跨 set 的重名 binding 编号拆开。 +## 生命周期 -### flat 模式 - -- 不建立 per-set 映射表。 -- getter 直接把 `binding` 当作实际 binding point 返回。 -- 只有 `setIndex == 0` 被视为有效。 - -## 设计取舍 - -- 这是纯 CPU 侧对象,不对应 OpenGL 驱动里的原生 pipeline layout 句柄。 -- 它更像商业引擎里“资源布局元数据”的后端特化版本。 -- 这样做的代价是: shader 反射与实际 layout 一致性,当前仍由调用方自己保证。 +- [OpenGLPipelineLayout()](Constructor.md) 初始化为空对象 +- [Initialize](Initialize.md) 构建描述缓存与映射表 +- 运行时通过一系列 `Has*Binding()` / `Get*BindingPoint()` 查询 +- [Shutdown](Shutdown.md) 清空内部缓存并把对象标记为未初始化 ## 当前限制 -- 不检查当前 shader program 是否真的声明了这些 binding。 -- 不使用 stage visibility 做更细粒度裁剪。 -- `Has*Binding()` 在 flat 模式下只验证 `setIndex == 0`,不会根据 count 严格判断某个 binding 是否越界。 +- 不对应 OpenGL 原生对象 +- 不校验 shader 里是否真的声明了这些 binding +- 不使用 stage visibility 做裁剪 +- flat 模式下的 `Has*Binding()` 只做 `setIndex == 0` 判断,不做更严格的 binding 越界验证 +- `GetDesc()` 暴露的是内部缓存引用,调用方需要注意生命周期 -## 重点方法 +## 关键方法 - [Initialize](Initialize.md) - [UsesSetLayouts](UsesSetLayouts.md) +- [HasConstantBufferBinding](HasConstantBufferBinding.md) - [GetConstantBufferBindingPoint](GetConstantBufferBindingPoint.md) - [GetShaderResourceBindingPoint](GetShaderResourceBindingPoint.md) - [GetUnorderedAccessBindingPoint](GetUnorderedAccessBindingPoint.md) @@ -70,6 +75,6 @@ OpenGL 的 UBO、采样纹理、image、sampler 都共享各自的全局编号 ## 相关文档 -- [OpenGL](../OpenGL.md) - [OpenGLDescriptorSet](../OpenGLDescriptorSet/OpenGLDescriptorSet.md) - [OpenGLCommandList](../OpenGLCommandList/OpenGLCommandList.md) +- [OpenGLUniformBufferManager](../OpenGLUniformBufferManager/OpenGLUniformBufferManager.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Shutdown.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Shutdown.md index bc7807e5..7b5c8c14 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Shutdown.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/Shutdown.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::Shutdown +# OpenGLPipelineLayout::Shutdown() ```cpp void Shutdown() override; @@ -6,15 +6,21 @@ void Shutdown() override; ## 作用 -清空内部保存的布局描述、映射表和初始化标志。 +清空当前 pipeline layout 的描述和映射缓存。 ## 当前实现行为 -- 重置 `m_desc`。 -- 清空 set layout 副本、binding point 映射和初始化标志。 -- 因为它是纯 CPU 元数据对象,所以没有 OpenGL 驱动资源需要释放。 +- 把 `m_desc` 重置为默认值 +- 清空 `m_setBindingPointMappings` +- 清空 `m_setLayouts` +- 清空 `m_setLayoutBindings` +- 把 `m_initialized` 置为 `false` + +## 设计说明 + +由于当前类不持有 GPU 资源,`Shutdown()` 的核心价值是显式回收 CPU 侧映射数据,并让 `GetNativeHandle()` / `UsesSetLayouts()` 等查询重新回到未初始化语义。 ## 相关文档 -- [Initialize](Initialize.md) - [GetNativeHandle](GetNativeHandle.md) +- [GetDesc](GetDesc.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/UsesSetLayouts.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/UsesSetLayouts.md index d42e0b8f..464af883 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/UsesSetLayouts.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLPipelineLayout/UsesSetLayouts.md @@ -1,4 +1,4 @@ -# OpenGLPipelineLayout::UsesSetLayouts +# OpenGLPipelineLayout::UsesSetLayouts() ```cpp bool UsesSetLayouts() const; @@ -6,16 +6,15 @@ bool UsesSetLayouts() const; ## 作用 -判断当前 pipeline layout 是否处于 set-aware 模式。 - -## 返回值 - -- `true`: `m_desc.setLayoutCount > 0` 且 `m_desc.setLayouts != nullptr`。 -- `false`: 当前使用 flat 模式。 +判断当前对象是否工作在 set-aware 模式。 ## 当前实现行为 -- 这个判断基于内部保存的 `m_desc`,而不是调用方传入对象的原始地址。 +- 返回 `m_desc.setLayoutCount > 0 && m_desc.setLayouts != nullptr` + +## 设计说明 + +这个判断不是看“初始化时是否传过原始 set layout”,而是看当前内部描述里是否仍然保存着有效的 set layout 指针和数量。因此它会受到 [Shutdown](Shutdown.md) 影响。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Bind.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Bind.md index da93c708..111f9dbb 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Bind.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Bind.md @@ -1,4 +1,4 @@ -# OpenGLSampler::Bind +# OpenGLSampler::Bind() ```cpp void Bind(unsigned int unit) override; @@ -8,19 +8,13 @@ void Bind(unsigned int unit) override; 把当前 sampler object 绑定到指定纹理单元。 -## 参数说明 - -- `unit`: 目标纹理单元编号。 - ## 当前实现行为 -- 直接调用 `glBindSampler(unit, m_sampler)`。 -- 不校验 `m_sampler` 是否有效,也不保存之前该纹理单元上的 sampler 绑定。 +- 直接调用 `glBindSampler(unit, m_sampler)` -## 使用建议 +## 设计说明 -- `unit` 必须与纹理绑定和着色器采样槽约定保持一致。 -- 如果对象尚未初始化,当前实现会把 `0` 绑定到该槽位,相当于未使用独立 sampler object。 +在 OpenGL 里,独立 sampler object 的好处是采样状态可以从纹理对象本身拆出来。`Bind(unit)` 正是把这份状态附着到某个纹理单元上,而不是修改纹理对象自身参数。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Constructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Constructor.md index b8ae422d..4823e4de 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Constructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Constructor.md @@ -1,4 +1,4 @@ -# OpenGLSampler::OpenGLSampler +# OpenGLSampler::OpenGLSampler() ```cpp OpenGLSampler(); @@ -6,15 +6,13 @@ OpenGLSampler(); ## 作用 -构造一个空的 OpenGL sampler 封装对象。 +构造一个尚未创建原生 sampler object 的对象。 ## 当前实现行为 -- 仅把 `m_sampler` 初始化为 `0`。 -- `m_desc` 使用结构体默认值。 -- 不执行任何 OpenGL 调用。 +- 把 `m_sampler` 初始化为 `0` ## 相关文档 - [Initialize](Initialize.md) -- [OpenGLSampler](OpenGLSampler.md) +- [GetID](GetID.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Destructor.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Destructor.md index 98dca118..bac3ef8d 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Destructor.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Destructor.md @@ -1,4 +1,4 @@ -# OpenGLSampler::~OpenGLSampler +# OpenGLSampler::~OpenGLSampler() ```cpp ~OpenGLSampler() override; @@ -6,19 +6,18 @@ ## 作用 -销毁 `OpenGLSampler` 对象本身。 +析构 sampler 对象。 ## 当前实现行为 -- 当前析构函数是空实现。 -- 它不会自动调用 [Shutdown](Shutdown.md)。 +- 析构函数是空实现 +- 不会自动调用 [Shutdown](Shutdown.md) -## 重要限制 +## 需要特别注意 -- 这意味着如果调用方在销毁前没有显式 `Shutdown()`,底层 sampler object 可能不会被及时删除。 -- 它和引擎中许多“析构里自动释放”的包装类行为不同,文档和使用者都必须注意这一点。 +如果对象已经成功创建原生 sampler,而调用方没有显式 `Shutdown()`,当前实现会把释放责任留给外部生命周期管理。 ## 相关文档 - [Shutdown](Shutdown.md) -- [Initialize](Initialize.md) +- [OpenGLSampler](OpenGLSampler.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetID.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetID.md index 7e9cf725..5fafca07 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetID.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetID.md @@ -1,4 +1,4 @@ -# OpenGLSampler::GetID +# OpenGLSampler::GetID() ```cpp unsigned int GetID() const; @@ -7,19 +7,14 @@ unsigned int GetID() override; ## 作用 -返回底层 OpenGL sampler object id。 - -## 返回值 - -- 初始化成功后通常返回非零 id。 -- 构造后或 `Shutdown()` 之后返回 `0`。 +返回底层 OpenGL sampler object ID。 ## 当前实现行为 -- 两个重载都直接返回 `m_sampler`。 -- 单元测试会校验初始化后该值非零。 +- 两个重载都直接返回 `m_sampler` +- `0` 表示当前尚未成功创建 sampler object,或者已经 [Shutdown](Shutdown.md) ## 相关文档 - [GetNativeHandle](GetNativeHandle.md) -- [Initialize](Initialize.md) +- [Bind](Bind.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetNativeHandle.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetNativeHandle.md index 57c4df51..0b97b371 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetNativeHandle.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/GetNativeHandle.md @@ -1,4 +1,4 @@ -# OpenGLSampler::GetNativeHandle +# OpenGLSampler::GetNativeHandle() ```cpp void* GetNativeHandle() override; @@ -6,16 +6,16 @@ void* GetNativeHandle() override; ## 作用 -以 `void*` 形式暴露底层 sampler 句柄。 - -## 返回值 - -- 返回 `m_sampler` 转换后的值。 +以统一句柄形式返回底层 sampler object。 ## 当前实现行为 -- 不创建新对象,也不附带其他副作用。 -- 其语义与 [GetID](GetID.md) 一致,只是为了适配统一 RHI 的 native handle 接口。 +- 把 `m_sampler` 转成 `uintptr_t` +- 再转成 `void*` 返回 + +## 注意事项 + +这个句柄本质上是 OpenGL 对象名,不是真正的原生指针对象。 ## 相关文档 diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Initialize.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Initialize.md index 096e68be..15455002 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Initialize.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Initialize.md @@ -1,4 +1,4 @@ -# OpenGLSampler::Initialize +# OpenGLSampler::Initialize() ```cpp bool Initialize(const OpenGLSamplerDesc& desc); @@ -6,24 +6,26 @@ bool Initialize(const OpenGLSamplerDesc& desc); ## 作用 -创建一个真正的 OpenGL sampler object,并把采样参数写入驱动。 +根据 `OpenGLSamplerDesc` 创建并配置独立 sampler object。 -## 参数说明 +## 参数 -- `desc`: 采样器描述,包含过滤模式、寻址模式、比较模式、LOD 范围、各向异性和边界色等参数。 +- `desc`: OpenGL 专用采样器描述 ## 返回值 -- 当前实现恒定返回 `true`。 +`bool`。当前实现始终返回 `true`。 ## 当前实现行为 -- 先复制 `desc` 到 `m_desc`。 -- 调用 `glGenSamplers(1, &m_sampler)` 创建原生 sampler。 -- 依次设置: +- 把 `desc` 复制到 `m_desc` +- 调用 `glGenSamplers(1, &m_sampler)` +- 依次设置: - `GL_TEXTURE_MIN_FILTER` - `GL_TEXTURE_MAG_FILTER` - - `GL_TEXTURE_WRAP_S/T/R` + - `GL_TEXTURE_WRAP_S` + - `GL_TEXTURE_WRAP_T` + - `GL_TEXTURE_WRAP_R` - `GL_TEXTURE_LOD_BIAS` - `GL_TEXTURE_MIN_LOD` - `GL_TEXTURE_MAX_LOD` @@ -32,13 +34,24 @@ bool Initialize(const OpenGLSamplerDesc& desc); - `GL_TEXTURE_COMPARE_FUNC` - `GL_TEXTURE_BORDER_COLOR` -## 重要限制 +## 与设备创建路径的关系 -- 当前实现没有检查 `glGenSamplers` 或参数设置是否失败。 -- `compareFunc` 作为原始整数直接传给 OpenGL,要求调用方或设备工厂提前完成正确映射。 -- 代码默认可用 `GL_TEXTURE_MAX_ANISOTROPY`,没有做扩展存在性保护。 +通常调用方不会手工拼 `OpenGLSamplerDesc`,而是经由 `OpenGLDevice::CreateSampler(const SamplerDesc&)` 走一层转换: + +- `FilterMode` 会被映射到 `SamplerFilter` +- `TextureAddressMode` 会被映射到 `SamplerWrapMode` +- `Comparison*` 过滤模式会启用 `CompareToRef` +- `MirrorOnce` 当前会被折叠为 `ClampToEdge` +- `maxAnisotropy`、`minLod`、`maxLod`、`borderColor` 会直接写入 + +## 需要特别注意 + +- 当前实现不检查 `glGenSamplers` 是否真的成功 +- 也不检查设置参数时的 OpenGL 错误 +- 若直接传入不适合 `GL_TEXTURE_MAG_FILTER` 的过滤枚举,当前代码不会做额外校验 ## 相关文档 - [Bind](Bind.md) - [Shutdown](Shutdown.md) +- [OpenGLSampler](OpenGLSampler.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/OpenGLSampler.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/OpenGLSampler.md index 702e92ed..68115bbd 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/OpenGLSampler.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/OpenGLSampler.md @@ -6,64 +6,60 @@ **头文件**: `XCEngine/RHI/OpenGL/OpenGLSampler.h` -**描述**: OpenGL 后端的独立 sampler object 封装,用于保存过滤、寻址、LOD 和比较采样状态。 +**描述**: OpenGL 后端的独立 sampler object 封装,用于保存过滤、寻址、LOD、比较采样和边框颜色等采样状态。 ## 概览 -和 `OpenGLResourceView` 那种“统一抽象视图元数据”不同,`OpenGLSampler` 对应的是一个真实的 OpenGL 原生对象: sampler object。 +`OpenGLSampler` 是当前后端里少数真正对应 OpenGL 原生对象的资源包装器之一。它的意义和现代图形 API 里的独立采样器对象一致: -这类对象的作用和商业引擎里的独立采样器资源一致: +- 纹理数据与采样状态解耦 +- 同一张纹理可以复用不同采样策略 +- descriptor set / resource binding 层更容易和 D3D12 / Vulkan 对齐 -- 把纹理采样状态从纹理对象本身拆出来 -- 让同一张纹理能以不同采样方式被复用 -- 让 descriptor / binding 层更接近现代图形 API 的资源组织方式 - -## 设计定位 - -`OpenGLSampler` 在当前引擎中承担的是“真实后端资源包装器”角色,而不是纯元数据对象。 - -它的好处是: - -- 采样状态可以独立于纹理复用 -- 更容易与上层 `RHISampler` 抽象对齐 - -当前实现的代价是: - -- 初始化路径非常直接,没有错误处理兜底 -- 析构函数没有自动释放原生对象,必须依赖显式 `Shutdown()` - -## 生命周期 - -- 构造后 `m_sampler = 0`。 -- [Initialize](Initialize.md) 成功后持有真实 sampler id。 -- [Shutdown](Shutdown.md) 删除 sampler object。 -- 析构函数当前不会自动执行 `Shutdown()`。 - -## 线程语义 - -- 不包含锁。 -- 所有操作都依赖当前 OpenGL 上下文,应视为渲染线程资源对象。 +这类设计在商业引擎里非常常见,因为它能让“材质要什么采样方式”和“纹理本身存了什么像素数据”保持分离。 ## 当前实现的真实行为 -- `OpenGLDevice::CreateSampler()` 会把通用 `SamplerDesc` 转换成 `OpenGLSamplerDesc`,再调用 [Initialize](Initialize.md)。 -- `OpenGLDescriptorSet` 在更新采样器时,会读取 [GetID](GetID.md) 保存 sampler id。 -- 单元测试 `tests/RHI/OpenGL/unit/test_sampler.cpp` 覆盖了默认初始化、自定义参数初始化、绑定/解绑和 `GetID()`。 +- [Initialize](Initialize.md) 会创建真实的 sampler object,并立即写入全部采样参数 +- [Bind](Bind.md) / [Unbind](Unbind.md) 直接作用于指定纹理单元 +- [GetID](GetID.md) 返回 OpenGL sampler 对象名 +- 析构函数为空实现,不自动 [Shutdown](Shutdown.md) +- 设备创建路径 `OpenGLDevice::CreateSampler(...)` 会先把通用 `SamplerDesc` 转成 `OpenGLSamplerDesc` +- `OpenGLDescriptorSet` 更新 sampler 时,会读取 `GetID()` 存下底层 sampler ID -## 当前限制 +## 设计背景 -- 析构不自动释放原生 sampler。 -- 初始化没有显式失败检测。 -- 比较函数和各向异性能力依赖调用环境和扩展支持。 +把 sampler 独立成对象有两个现实收益: + +- 一张纹理可以被多个材质以不同过滤/寻址方式复用 +- 跨后端 RHI 不必因为 OpenGL 而退化回“把采样参数写死在纹理对象里”的旧式接口 + +这也是商业级引擎常见的抽象路线:高层接口尽量保持现代资源模型,后端尽量映射到平台支持的最接近对象。 + +## 生命周期 + +- [OpenGLSampler()](Constructor.md) 初始化 `m_sampler = 0` +- [Initialize](Initialize.md) 创建原生 sampler object +- [Bind](Bind.md) 把它绑定到某个纹理单元 +- [Shutdown](Shutdown.md) 删除 sampler object + +## 重要限制 + +- 析构不自动释放原生 sampler +- 初始化没有显式错误检测 +- 各向异性和比较采样能力依赖运行环境支持 +- 直接使用 `OpenGLSamplerDesc` 时,调用方需要自己保证参数组合适合 OpenGL ## 关键方法 - [Initialize](Initialize.md) - [Bind](Bind.md) - [Unbind](Unbind.md) +- [GetID](GetID.md) - [Shutdown](Shutdown.md) ## 相关文档 -- [OpenGL](../OpenGL.md) - [OpenGLDescriptorSet](../OpenGLDescriptorSet/OpenGLDescriptorSet.md) +- [OpenGLTexture](../OpenGLTexture/OpenGLTexture.md) +- [OpenGLDevice](../OpenGLDevice/OpenGLDevice.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Shutdown.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Shutdown.md index 5a2d6d97..96139648 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Shutdown.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Shutdown.md @@ -1,4 +1,4 @@ -# OpenGLSampler::Shutdown +# OpenGLSampler::Shutdown() ```cpp void Shutdown() override; @@ -6,20 +6,19 @@ void Shutdown() override; ## 作用 -删除底层 sampler object。 +删除当前持有的 sampler object。 ## 当前实现行为 -- 如果 `m_sampler != 0`,调用 `glDeleteSamplers(1, &m_sampler)`。 -- 然后把 `m_sampler` 设回 `0`。 -- 不会清空 `m_desc`。 +- 若 `m_sampler != 0`,调用 `glDeleteSamplers(1, &m_sampler)` +- 然后把 `m_sampler` 置为 `0` -## 使用建议 +## 需要特别注意 -- 由于析构函数不会自动调用它,调用方应把 `Shutdown()` 当作释放原生 sampler 的必经步骤。 -- 多次调用是安全的,后续调用会因 `m_sampler == 0` 而成为 no-op。 +- `m_desc` 不会被重置 +- 因此对象失去原生句柄后,仍保留上一次初始化时的 CPU 侧描述缓存 ## 相关文档 - [Destructor](Destructor.md) -- [GetID](GetID.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Unbind.md b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Unbind.md index c6552474..9d53ca17 100644 --- a/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Unbind.md +++ b/docs/api/XCEngine/RHI/OpenGL/OpenGLSampler/Unbind.md @@ -1,4 +1,4 @@ -# OpenGLSampler::Unbind +# OpenGLSampler::Unbind() ```cpp void Unbind(unsigned int unit) override; @@ -6,18 +6,13 @@ void Unbind(unsigned int unit) override; ## 作用 -从指定纹理单元解绑独立 sampler object。 - -## 参数说明 - -- `unit`: 目标纹理单元编号。 +把指定纹理单元上的 sampler object 解绑。 ## 当前实现行为 -- 直接执行 `glBindSampler(unit, 0)`。 -- 不要求当前对象已经初始化,因为它不依赖 `m_sampler`。 +- 直接调用 `glBindSampler(unit, 0)` ## 相关文档 - [Bind](Bind.md) -- [Shutdown](Shutdown.md) +- [GetID](GetID.md) diff --git a/docs/api/_meta/rebuild-status.md b/docs/api/_meta/rebuild-status.md index f2f64a71..fb9492c6 100644 --- a/docs/api/_meta/rebuild-status.md +++ b/docs/api/_meta/rebuild-status.md @@ -1,6 +1,6 @@ # API 文档重构状态 -**生成时间**: `2026-03-28 01:17:27` +**生成时间**: `2026-03-28 01:38:41` **来源**: `docs/api/_tools/audit_api_docs.py`