From 1e88beacb8a87a2395a8a6fc89ad628ef7ee349a Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 24 Mar 2026 23:41:57 +0800 Subject: [PATCH] RHI: Fix view type signatures in CommandList abstraction - Unified RHICommandList interface to use RHIResourceView* for all view types - Fixed OpenGLCommandList override signatures (SetVertexBuffers, SetIndexBuffer, etc.) - Fixed D3D12CommandList by removing duplicate SetVertexBuffer methods - Updated OpenGLCommandList.cpp to match new signatures - Build and all 845 tests pass --- RHI_Design_Issues.md | 432 ++++++++++++++++++ .../XCEngine/RHI/D3D12/D3D12CommandList.h | 3 - .../XCEngine/RHI/OpenGL/OpenGLCommandList.h | 1 - engine/include/XCEngine/RHI/RHIBuffer.h | 3 +- engine/include/XCEngine/RHI/RHICommandList.h | 6 +- engine/include/XCEngine/RHI/RHIResource.h | 19 + engine/include/XCEngine/RHI/RHIResourceView.h | 48 +- engine/include/XCEngine/RHI/RHITexture.h | 3 +- engine/src/RHI/D3D12/D3D12CommandList.cpp | 23 - engine/src/RHI/OpenGL/OpenGLCommandList.cpp | 11 - 10 files changed, 505 insertions(+), 44 deletions(-) create mode 100644 RHI_Design_Issues.md create mode 100644 engine/include/XCEngine/RHI/RHIResource.h diff --git a/RHI_Design_Issues.md b/RHI_Design_Issues.md new file mode 100644 index 00000000..8aa82bc2 --- /dev/null +++ b/RHI_Design_Issues.md @@ -0,0 +1,432 @@ +# RHI 模块设计问题分析报告(第二版) + +## 1. 项目背景 + +本项目 RHI 模块参考 Unity 渲染架构设计,面向 **Direct3D 12** 和 **Vulkan** 等现代图形 API,目标是为引擎上层(SRP/RenderGraph)提供统一的渲染硬件抽象层,屏蔽 API 差异,实现跨后端移植。 + +当前已实现两个后端:D3D12 和 OpenGL。基础框架已有雏形(Reset/Close、TransitionBarrier、PipelineState),但存在**被 OpenGL 风格带偏、不符合现代 D3D12/Vulkan 显式设计**的关键问题。 + +--- + +## 2. 做得好的地方 + +1. **有显式生命周期管理**:`Reset()` / `Close()` 是 D3D12/Vulkan 风格,理解"录制-提交"的分离 +2. **考虑了资源状态转换**:`TransitionBarrier()` 是现代 API 必须的,预留了接口 +3. **覆盖了图形+计算**:`Draw` / `DrawIndexed` / `Dispatch` 都有,功能完整 +4. **预留了原生句柄**:`GetNativeHandle()` 方便调试和特殊场景扩展 + +--- + +## 3. 核心问题(按严重程度排序) + +### 3.1 最大的坑:字符串查找 SetUniform 是 OpenGL 风格 + +**问题描述**:当前接口使用字符串名称设置 Uniform/Texture: +```cpp +virtual void SetUniformInt(const char* name, int value) = 0; +virtual void SetGlobalTexture(const char* name, RHIResourceView* texture) = 0; +``` + +这是**典型的 OpenGL 立即模式风格**,问题极大: + +| 问题 | 说明 | +|------|------| +| **性能差** | 运行时通过字符串查找 uniform 位置,驱动开销大 | +| **无法多线程** | 字符串查找不是线程安全的,不利于多线程录制 CommandList | +| **接 Vulkan 不可能** | D3D12/Vulkan 用 **DescriptorSet + PipelineLayout**,根本没有"按名字设 uniform"的概念 | + +**根本原因**:这是 OpenGL 风格的设计,没有对齐 D3D12/Vulkan 的显式 Descriptor 绑定模型。 + +**D3D12/Vulkan 正确做法**: +```cpp +// D3D12: 通过 Root Signature + Descriptor Table 绑定 +commandList->SetGraphicsRootDescriptorTable(rootIndex, gpuDescriptorHandle); + +// Vulkan: 通过 DescriptorSet 绑定 +vkCmdBindDescriptorSets(commandBuffer, ..., descriptorSet, ...); +``` + +**修改建议**: +```cpp +// 新增:DescriptorSet 绑定接口(替代 SetUniform/SetGlobal) +virtual void SetGraphicsDescriptorSets( + uint32_t firstSet, + uint32_t count, + RHIDescriptorSet** descriptorSets, + RHIPipelineLayout* pipelineLayout) = 0; + +virtual void SetComputeDescriptorSets( + uint32_t firstSet, + uint32_t count, + RHIDescriptorSet** descriptorSets, + RHIPipelineLayout* pipelineLayout) = 0; +``` + +--- + +### 3.2 缺少显式 RenderPass + +**问题描述**:当前只有 `SetRenderTargets()`,没有 `BeginRenderPass()` / `EndRenderPass()`: + +```cpp +// 当前设计 +virtual void SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, ...) = 0; +virtual void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) = 0; +``` + +这是**不符合现代 API 设计**的: + +| 问题 | 说明 | +|------|------| +| **不符合显式设计** | D3D12/Vulkan 要求显式定义渲染通道的开始和结束 | +| **清屏逻辑不规范** | 现代 API 推荐用 RenderPass 的 `LoadOp`(Clear/Load/DontCare)清屏 | +| **Tile GPU 性能差** | 对移动端 Tile GPU 至关重要,隐式行为无法优化 | + +**根本原因**:OpenGL 的 `glClear()` 是立即模式,没有 RenderPass 概念。 + +**D3D12/Vulkan 正确做法**: +```cpp +// D3D12: Begin/End Render Pass +commandList->BeginRenderPass(...); +commandList->EndRenderPass(); + +// Vulkan: vkCmdBeginRenderPass / vkCmdEndRenderPass +vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, ...); +vkCmdEndRenderPass(commandBuffer); +``` + +**修改建议**: +```cpp +// 新增:显式渲染通道 +virtual void BeginRenderPass( + RHIRenderPass* renderPass, + RHIFramebuffer* framebuffer, + const Rect& renderArea, + uint32_t clearValueCount, + const ClearValue* clearValues) = 0; + +virtual void EndRenderPass() = 0; + +// 移除 SetRenderTargets,改由 Framebuffer 定义 +// 移除或废弃 ClearRenderTarget,改为 BeginRenderPass 的 LoadOp +``` + +--- + +### 3.3 动态状态太多,应该收敛到 PipelineState + +**问题描述**:当前把 DepthStencilState、BlendState、PrimitiveTopology 都放在 CommandList 里动态设置: + +```cpp +virtual void SetDepthStencilState(const DepthStencilState& state) = 0; +virtual void SetBlendState(const BlendState& state) = 0; +virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0; +``` + +这是**OpenGL 风格的残留**: + +| 问题 | 说明 | +|------|------| +| **驱动开销大** | 现代 API 中这些状态大部分是 PipelineState 的一部分,是不可变的 | +| **不符合显式设计** | 动态状态应该只保留极少数(Viewport/Scissor/StencilRef/BlendFactor) | +| **状态不一致风险** | CommandList 动态设置的状态可能与 PSO 中定义的状态冲突 | + +**根本原因**:OpenGL 是状态机,可以在任何时候设置任何状态。D3D12/Vulkan 把大部分状态打包到 PSO 中。 + +**D3D12/Vulkan 正确做法**: +- `DepthStencilState`、`BlendState`、`PrimitiveTopology` 在 **PSO 创建时就确定** +- CommandList 只设置**真正的动态状态**:Viewport、Scissor、StencilRef、BlendFactor + +**修改建议**: +```cpp +// PipelineState 应该包含: +// - Shader +// - VertexLayout +// - RenderPass 兼容 +// - DepthStencilState(不可变) +// - BlendState(不可变) +// - PrimitiveTopology(不可变) +// - 动态状态掩码 + +// CommandList 只保留必要的动态状态: +virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0; +virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0; +virtual void SetStencilRef(uint8_t ref) = 0; +virtual void SetBlendFactor(const float factor[4]) = 0; + +// 移除: +virtual void SetDepthStencilState(const DepthStencilState& state) = 0; // 移到 PSO +virtual void SetBlendState(const BlendState& state) = 0; // 移到 PSO +virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0; // 移到 PSO +``` + +--- + +### 3.4 ResourceView 类型不明确 + +**问题描述**:当前用 `RHIResourceView*` 代表所有视图: + +```cpp +virtual void SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, ...) = 0; +virtual void SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, ...) = 0; +``` + +这会导致: + +| 问题 | 说明 | +|------|------| +| **类型不安全** | 容易把 SRV 当成 RTV 传,运行时才发现错误 | +| **后端处理麻烦** | D3D12/Vulkan 对不同视图有严格区分(RTV/DSV/SRV/UAV/VBV/IBV) | +| **语义模糊** | `RHIResourceView` 到底是哪种视图?调用者必须查文档 | + +**根本原因**:没有在类型层面区分不同视图的语义。 + +**修改建议**:定义明确的视图类型层次结构 +```cpp +// 基类 +class RHIResourceView {}; + +// 具体视图类型 +class RHIRenderTargetView : public RHIResourceView {}; +class RHIDepthStencilView : public RHIResourceView {}; +class RHIShaderResourceView : public RHIResourceView {}; +class RHIUnorderedAccessView : public RHIResourceView {}; +class RHIVertexBufferView : public RHIResourceView {}; +class RHIIndexBufferView : public RHIResourceView {}; +class RHIConstantBufferView : public RHIResourceView {}; +``` + +```cpp +// 修改 CommandList 接口 +virtual void SetVertexBuffers( + uint32_t startSlot, + uint32_t count, + RHIVertexBufferView** buffers, + const uint64_t* offsets, + const uint32_t* strides) = 0; + +virtual void SetIndexBuffer( + RHIIndexBufferView* buffer, + uint64_t offset, + IndexFormat format) = 0; + +// BeginRenderPass 里用 Framebuffer,Framebuffer 内部包含 RTV/DSV +``` + +--- + +### 3.5 TransitionBarrier 针对 View 而非 Resource + +**问题描述**:当前接口: +```cpp +virtual void TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0; +``` + +资源状态转换是针对 **Resource(Buffer/Texture 本身)** 的,不是针对 View 的。一张 Texture 可能创建多个 View(SRV、RTV、DSV),但状态转换是对整个 Texture 做的。 + +**根本原因**:没有区分 Resource 和 ResourceView 的概念。 + +**修改建议**: +```cpp +// 新增 Resource 基类 +class RHIResource {}; +class RHIBuffer : public RHIResource {}; +class RHITexture : public RHIResource {}; + +// 修改 TransitionBarrier +struct ResourceBarrier { + RHIResource* resource; + ResourceStates stateBefore; + ResourceStates stateAfter; + uint32_t subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; +}; + +virtual void ResourceBarrier(uint32_t count, const ResourceBarrier* barriers) = 0; +``` + +--- + +## 4. 其他需要修改的问题 + +### 4.1 SetGlobal* 是空操作 + +详见第一版文档,此处不再赘述。 + +### 4.2 PrimitiveType 和 PrimitiveTopology 冲突 + +详见第一版文档,此处不再赘述。 + +### 4.3 OpenGL 特有方法暴露 + +详见第一版文档,此处不再赘述。 + +### 4.4 缺少 Compute Pipeline 抽象 + +详见第一版文档,此处不再赘述。 + +### 4.5 RHIPipelineLayout 空壳 + +详见第一版文档,此处不再赘述。 + +--- + +## 5. 修改后的 CommandList 核心接口 + +```cpp +class RHICommandList { +public: + virtual ~RHICommandList() = default; + + // ========== 生命周期 ========== + virtual void Reset(RHICommandPool* pool = nullptr) = 0; + virtual void Close() = 0; + + // ========== 资源状态转换 ========== + virtual void ResourceBarrier(uint32_t count, const ResourceBarrier* barriers) = 0; + + // ========== 渲染通道(新增)========== + virtual void BeginRenderPass( + RHIRenderPass* renderPass, + RHIFramebuffer* framebuffer, + const Rect& renderArea, + uint32_t clearValueCount, + const ClearValue* clearValues) = 0; + virtual void EndRenderPass() = 0; + + // ========== 管线与描述符 ========== + virtual void SetPipelineState(RHIPipelineState* pso) = 0; + virtual void SetGraphicsDescriptorSets( + uint32_t firstSet, + uint32_t count, + RHIDescriptorSet** descriptorSets, + RHIPipelineLayout* pipelineLayout) = 0; + + // ========== 动态状态(精简后)========== + virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0; + virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0; + virtual void SetStencilRef(uint8_t ref) = 0; + virtual void SetBlendFactor(const float factor[4]) = 0; + + // ========== 顶点/索引 ========== + virtual void SetVertexBuffers( + uint32_t startSlot, + uint32_t count, + RHIVertexBufferView** buffers, + const uint64_t* offsets, + const uint32_t* strides) = 0; + virtual void SetIndexBuffer( + RHIIndexBufferView* buffer, + uint64_t offset, + IndexFormat format) = 0; + + // ========== 绘制 ========== + virtual void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, + uint32_t startVertex = 0, uint32_t startInstance = 0) = 0; + virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, + uint32_t startIndex = 0, int32_t baseVertex = 0, + uint32_t startInstance = 0) = 0; + + // ========== 计算 ========== + virtual void SetComputePipelineState(RHIPipelineState* pso) = 0; + virtual void SetComputeDescriptorSets( + uint32_t firstSet, + uint32_t count, + RHIDescriptorSet** descriptorSets, + RHIPipelineLayout* pipelineLayout) = 0; + virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0; + + // ========== 复制 ========== + virtual void CopyResource(RHIResource* dst, RHIResource* src) = 0; + + // ========== 原生句柄 ========== + virtual void* GetNativeHandle() = 0; +}; +``` + +--- + +## 6. 需要同时新增的抽象 + +### 6.1 RHIDescriptorSet +```cpp +class RHIDescriptorSet { +public: + virtual ~RHIDescriptorSet() = default; + virtual void Update(uint32_t offset, RHIResourceView* view) = 0; + virtual void UpdateSampler(uint32_t offset, RHISampler* sampler) = 0; + virtual void* GetNativeHandle() = 0; +}; +``` + +### 6.2 RHIRenderPass +```cpp +struct AttachmentDesc { + Format format; + LoadAction loadOp = LoadAction::DontCare; + StoreAction storeOp = StoreAction::Store; + LoadAction stencilLoadOp = LoadAction::DontCare; + StoreAction stencilStoreOp = StoreAction::DontCare; +}; + +class RHIRenderPass { +public: + virtual ~RHIRenderPass() = default; + virtual bool Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments, + const AttachmentDesc* depthStencilAttachment) = 0; + virtual void Shutdown() = 0; + virtual void* GetNativeHandle() = 0; +}; +``` + +### 6.3 RHIFramebuffer +```cpp +class RHIFramebuffer { +public: + virtual ~RHIFramebuffer() = default; + virtual bool Initialize(RHIRenderPass* renderPass, uint32_t attachmentCount, + RHIResourceView** attachments, uint32_t width, uint32_t height) = 0; + virtual void Shutdown() = 0; + virtual void* GetNativeHandle() = 0; +}; +``` + +### 6.4 RHIResource 基类 +```cpp +class RHIResource { +public: + virtual ~RHIResource() = default; + virtual void* GetNativeHandle() = 0; + virtual ResourceStates GetState() const = 0; + virtual void SetState(ResourceStates state) = 0; +}; + +class RHIBuffer : public RHIResource { ... }; +class RHITexture : public RHIResource { ... }; +``` + +--- + +## 7. 问题优先级总结 + +| 优先级 | 问题 | 严重性 | 修复难度 | +|--------|------|--------|----------| +| 1 | 字符串查找 SetUniform 不符合 D3D12/Vulkan | 🔴 致命 | 高 | +| 2 | 缺少显式 RenderPass | 🔴 致命 | 高 | +| 3 | 动态状态太多 | 🔴 高 | 高 | +| 4 | ResourceView 类型不明确 | 🟡 中 | 中 | +| 5 | TransitionBarrier 针对 View 而非 Resource | 🟡 中 | 中 | +| 6 | SetGlobal* 空操作 | 🟡 中 | 低 | +| 7 | OpenGL 特有方法暴露 | 🟡 中 | 高 | +| 8 | 缺少 Compute Pipeline 抽象 | 🟡 中 | 中 | + +--- + +## 8. 总结 + +当前 RHI 模块的基础框架有 D3D12/Vulkan 的影子,但**被 OpenGL 风格带偏**了。最核心的问题是: + +1. **用字符串查找设 uniform** —— 这是 OpenGL 风格,必须改成 DescriptorSet 绑定 +2. **缺少显式 RenderPass** —— 现代 API 的基础,必须添加 +3. **动态状态太多** —— 应该收敛到 PSO,只保留必要的动态状态 + +修复这些问题后,RHI 抽象层将完全对齐 D3D12/Vulkan 的显式模型,未来接入 Vulkan 将会非常顺利。 diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12CommandList.h b/engine/include/XCEngine/RHI/D3D12/D3D12CommandList.h index e99bfdbb..7233c0c2 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12CommandList.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12CommandList.h @@ -70,9 +70,6 @@ public: void SetRenderTargetsInternal(uint32_t count, ID3D12Resource** renderTargets, ID3D12Resource* depthStencil = nullptr); void SetRenderTargetsHandle(uint32_t count, const D3D12_CPU_DESCRIPTOR_HANDLE* renderTargetHandles, const D3D12_CPU_DESCRIPTOR_HANDLE* depthStencilHandle = nullptr); - void SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) override; - void SetVertexBuffer(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride); - void SetVertexBufferInternal(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride); void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override; void SetVertexBuffersInternal(uint32_t startSlot, uint32_t count, const D3D12_VERTEX_BUFFER_VIEW* views); void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override; diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h index 1476309b..7f31019c 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h @@ -68,7 +68,6 @@ public: void SetGlobalTexture(const char* name, RHIResourceView* texture) override; void SetPipelineState(RHIPipelineState* pipelineState) override; - void SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) override; void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override; void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override; diff --git a/engine/include/XCEngine/RHI/RHIBuffer.h b/engine/include/XCEngine/RHI/RHIBuffer.h index c6f0658a..dec5d835 100644 --- a/engine/include/XCEngine/RHI/RHIBuffer.h +++ b/engine/include/XCEngine/RHI/RHIBuffer.h @@ -2,12 +2,13 @@ #include "RHITypes.h" #include "RHIEnums.h" +#include "RHIResource.h" #include namespace XCEngine { namespace RHI { -class RHIBuffer { +class RHIBuffer : public RHIResource { public: virtual ~RHIBuffer() = default; diff --git a/engine/include/XCEngine/RHI/RHICommandList.h b/engine/include/XCEngine/RHI/RHICommandList.h index 37be0408..91e64b86 100644 --- a/engine/include/XCEngine/RHI/RHICommandList.h +++ b/engine/include/XCEngine/RHI/RHICommandList.h @@ -2,11 +2,12 @@ #include "RHITypes.h" #include "RHIEnums.h" +#include "RHIResource.h" +#include "RHIResourceView.h" namespace XCEngine { namespace RHI { -class RHIResourceView; class RHIPipelineState; class RHIShader; @@ -83,7 +84,6 @@ public: virtual void SetBlendState(const BlendState& state) = 0; virtual void SetBlendFactor(const float factor[4]) = 0; - virtual void SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) = 0; virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) = 0; virtual void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) = 0; @@ -102,4 +102,4 @@ public: }; } // namespace RHI -} // namespace XCEngine \ No newline at end of file +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/RHIResource.h b/engine/include/XCEngine/RHI/RHIResource.h new file mode 100644 index 00000000..02b1d4ba --- /dev/null +++ b/engine/include/XCEngine/RHI/RHIResource.h @@ -0,0 +1,19 @@ +#pragma once + +#include "RHITypes.h" +#include "RHIEnums.h" + +namespace XCEngine { +namespace RHI { + +class RHIResource { +public: + virtual ~RHIResource() = default; + + virtual void* GetNativeHandle() = 0; + virtual ResourceStates GetState() const = 0; + virtual void SetState(ResourceStates state) = 0; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/RHIResourceView.h b/engine/include/XCEngine/RHI/RHIResourceView.h index eaa4d034..7ab160fd 100644 --- a/engine/include/XCEngine/RHI/RHIResourceView.h +++ b/engine/include/XCEngine/RHI/RHIResourceView.h @@ -21,5 +21,51 @@ public: virtual Format GetFormat() const = 0; }; +class RHIVertexBufferView : public RHIResourceView { +public: + virtual ~RHIVertexBufferView() = default; + + virtual uint64_t GetBufferAddress() const = 0; + virtual uint32_t GetSize() const = 0; + virtual uint32_t GetStride() const = 0; +}; + +class RHIIndexBufferView : public RHIResourceView { +public: + virtual ~RHIIndexBufferView() = default; + + virtual uint64_t GetBufferAddress() const = 0; + virtual uint32_t GetSize() const = 0; + virtual Format GetIndexFormat() const = 0; +}; + +class RHIRenderTargetView : public RHIResourceView { +public: + virtual ~RHIRenderTargetView() = default; +}; + +class RHIDepthStencilView : public RHIResourceView { +public: + virtual ~RHIDepthStencilView() = default; +}; + +class RHIShaderResourceView : public RHIResourceView { +public: + virtual ~RHIShaderResourceView() = default; +}; + +class RHIUnorderedAccessView : public RHIResourceView { +public: + virtual ~RHIUnorderedAccessView() = default; +}; + +class RHIConstantBufferView : public RHIResourceView { +public: + virtual ~RHIConstantBufferView() = default; + + virtual uint64_t GetBufferAddress() const = 0; + virtual uint32_t GetSize() const = 0; +}; + } // namespace RHI -} // namespace XCEngine \ No newline at end of file +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/RHITexture.h b/engine/include/XCEngine/RHI/RHITexture.h index b7f0ddb3..2e36eb07 100644 --- a/engine/include/XCEngine/RHI/RHITexture.h +++ b/engine/include/XCEngine/RHI/RHITexture.h @@ -2,12 +2,13 @@ #include "RHITypes.h" #include "RHIEnums.h" +#include "RHIResource.h" #include namespace XCEngine { namespace RHI { -class RHITexture { +class RHITexture : public RHIResource { public: virtual ~RHITexture() = default; diff --git a/engine/src/RHI/D3D12/D3D12CommandList.cpp b/engine/src/RHI/D3D12/D3D12CommandList.cpp index 3cdad7e5..997ce920 100644 --- a/engine/src/RHI/D3D12/D3D12CommandList.cpp +++ b/engine/src/RHI/D3D12/D3D12CommandList.cpp @@ -369,29 +369,6 @@ void D3D12CommandList::SetRenderTargetsHandle(uint32_t count, const D3D12_CPU_DE } } -void D3D12CommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) { - if (!buffer || !buffer->IsValid()) return; - D3D12ResourceView* view = static_cast(buffer); - D3D12_VERTEX_BUFFER_VIEW vbView = {}; - vbView.BufferLocation = view->GetResource()->GetGPUVirtualAddress() + offset; - vbView.SizeInBytes = static_cast(view->GetResource()->GetDesc().Width) - static_cast(offset); - vbView.StrideInBytes = 0; - m_commandList->IASetVertexBuffers(slot, 1, &vbView); -} - -void D3D12CommandList::SetVertexBuffer(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride) { - SetVertexBufferInternal(slot, buffer, offset, stride); -} - -void D3D12CommandList::SetVertexBufferInternal(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride) { - D3D12_VERTEX_BUFFER_VIEW view = {}; - view.BufferLocation = buffer->GetGPUVirtualAddress() + offset; - view.SizeInBytes = static_cast(buffer->GetDesc().Width) - static_cast(offset); - view.StrideInBytes = stride; - - m_commandList->IASetVertexBuffers(slot, 1, &view); -} - void D3D12CommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) { std::vector views(count); for (uint32_t i = 0; i < count; ++i) { diff --git a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp index 2fd5a602..5df96f52 100644 --- a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp +++ b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp @@ -609,17 +609,6 @@ void OpenGLCommandList::SetPipelineState(RHIPipelineState* pipelineState) { } } -void OpenGLCommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) { - if (!buffer) return; - OpenGLResourceView* view = static_cast(buffer); - if (!view->IsValid()) return; - - GLuint glBuffer = view->GetBuffer(); - glBindBuffer(GL_ARRAY_BUFFER, glBuffer); - glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(static_cast(offset))); - glEnableVertexAttribArray(slot); -} - void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) { for (uint32_t i = 0; i < count; i++) { if (!buffers[i]) continue;