refactor: 删除旧的RHI实现,添加D3D12测试用例和第二阶段计划
This commit is contained in:
808
docs/plan/第二阶段计划.md
Normal file
808
docs/plan/第二阶段计划.md
Normal file
@@ -0,0 +1,808 @@
|
|||||||
|
# 第二阶段计划:RHI 渲染硬件抽象层
|
||||||
|
|
||||||
|
> **目标**:构建跨平台的渲染硬件抽象层,支持多后端(D3D12、Vulkan等)
|
||||||
|
> **阶段**:第二阶段
|
||||||
|
> **前置依赖**:第一阶段核心基础层(数学库、内存管理、线程系统)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.1 阶段目标
|
||||||
|
|
||||||
|
实现完整的RHI抽象层,提供:
|
||||||
|
- 统一的图形API抽象接口
|
||||||
|
- D3D12后端完整实现
|
||||||
|
- 资源管理(纹理、缓冲区)
|
||||||
|
- 命令流提交机制
|
||||||
|
- 同步与同步原语
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.2 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
RHI/ # 渲染硬件抽象层
|
||||||
|
├── RHISystem.h # RHI 系统入口
|
||||||
|
├── RHIDevice.h # 抽象设备接口
|
||||||
|
├── Types.h # 通用类型定义
|
||||||
|
├── Enums.h # 枚举定义
|
||||||
|
├── Resource.h # 资源基类接口
|
||||||
|
├── ResourceView.h # 资源视图基类接口
|
||||||
|
├── RenderTargetView.h # 渲染目标视图接口
|
||||||
|
├── DepthStencilView.h # 深度模板视图接口
|
||||||
|
├── ShaderResourceView.h # 着色器资源视图接口
|
||||||
|
├── UnorderedAccessView.h # 无序访问视图接口
|
||||||
|
├── ConstantBufferView.h # 常量缓冲区视图接口
|
||||||
|
├── CommandQueue.h # 命令队列
|
||||||
|
├── CommandList.h # 命令列表
|
||||||
|
├── CommandAllocator.h # 命令分配器
|
||||||
|
├── Fence.h # 同步围栏
|
||||||
|
├── DescriptorHeap.h # 描述符堆
|
||||||
|
├── QueryHeap.h # 查询堆
|
||||||
|
├── RootSignature.h # 根签名
|
||||||
|
├── PipelineState.h # 管线状态
|
||||||
|
├── Sampler.h # 采样器
|
||||||
|
├── SwapChain.h # 交换链
|
||||||
|
├── Texture.h # 纹理资源
|
||||||
|
├── Buffer.h # 缓冲区资源
|
||||||
|
├── Shader.h # 着色器
|
||||||
|
└── D3D12/ # D3D12 后端实现
|
||||||
|
├── D3D12Device.h
|
||||||
|
├── D3D12Device.cpp
|
||||||
|
├── D3D12CommandList.h
|
||||||
|
├── D3D12CommandList.cpp
|
||||||
|
├── D3D12CommandQueue.h
|
||||||
|
├── D3D12CommandQueue.cpp
|
||||||
|
├── D3D12CommandAllocator.h
|
||||||
|
├── D3D12CommandAllocator.cpp
|
||||||
|
├── D3D12Fence.h
|
||||||
|
├── D3D12Fence.cpp
|
||||||
|
├── D3D12DescriptorHeap.h
|
||||||
|
├── D3D12DescriptorHeap.cpp
|
||||||
|
├── D3D12QueryHeap.h
|
||||||
|
├── D3D12QueryHeap.cpp
|
||||||
|
├── D3D12RootSignature.h
|
||||||
|
├── D3D12RootSignature.cpp
|
||||||
|
├── D3D12PipelineState.h
|
||||||
|
├── D3D12PipelineState.cpp
|
||||||
|
├── D3D12Sampler.h
|
||||||
|
├── D3D12Sampler.cpp
|
||||||
|
├── D3D12SwapChain.h
|
||||||
|
├── D3D12SwapChain.cpp
|
||||||
|
├── D3D12Texture.h
|
||||||
|
├── D3D12Texture.cpp
|
||||||
|
├── D3D12Buffer.h
|
||||||
|
├── D3D12Buffer.cpp
|
||||||
|
├── D3D12Shader.h
|
||||||
|
├── D3D12Shader.cpp
|
||||||
|
├── D3D12RenderTargetView.h
|
||||||
|
├── D3D12RenderTargetView.cpp
|
||||||
|
├── D3D12DepthStencilView.h
|
||||||
|
├── D3D12DepthStencilView.cpp
|
||||||
|
├── D3D12ShaderResourceView.h
|
||||||
|
├── D3D12ShaderResourceView.cpp
|
||||||
|
├── D3D12UnorderedAccessView.h
|
||||||
|
├── D3D12UnorderedAccessView.cpp
|
||||||
|
├── D3D12ConstantBufferView.h
|
||||||
|
├── D3D12ConstantBufferView.cpp
|
||||||
|
└── D3D12Common.h # 公共定义
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.3 任务拆分
|
||||||
|
|
||||||
|
### 2.3.1 基础枚举与类型定义
|
||||||
|
|
||||||
|
**任务 2.1:Enums.h - 枚举定义**
|
||||||
|
|
||||||
|
定义所有渲染相关的枚举类型:
|
||||||
|
- `Format` - 像素格式
|
||||||
|
- `ResourceStates` - 资源状态
|
||||||
|
- `ShaderType` - 着色器类型
|
||||||
|
- `PrimitiveTopology` - 图元拓扑
|
||||||
|
- `CullMode` / `FillMode` - 剔除/填充模式
|
||||||
|
- `BlendOp` / `BlendFactor` - 混合操作/因子
|
||||||
|
- `ComparisonFunc` - 比较函数
|
||||||
|
- `StencilOp` - 模板操作
|
||||||
|
- `TextureType` - 纹理类型
|
||||||
|
- `BufferType` - 缓冲区类型
|
||||||
|
- `QueryType` - 查询类型
|
||||||
|
- `DescriptorType` - 描述符类型
|
||||||
|
- `PipelineType` - 管线类型
|
||||||
|
- `CommandQueueType` - 命令队列类型
|
||||||
|
- `LoadAction` / `StoreAction` - 渲染目标加载/存储操作
|
||||||
|
- `PresentFlags` - 呈现标志
|
||||||
|
- `IndirectDrawArguments` - 间接绘制参数
|
||||||
|
- `IndirectDispatchArguments` - 间接调度参数
|
||||||
|
|
||||||
|
**任务 2.1.2:类型定义 - Types.h**
|
||||||
|
|
||||||
|
定义通用结构体(不依赖特定图形API):
|
||||||
|
- `Viewport` - 视口
|
||||||
|
- `Rect` - 矩形区域
|
||||||
|
- `Color` - 颜色
|
||||||
|
- `ClearValue` - 清空值
|
||||||
|
- `ShaderCompileDesc` - 着色器编译描述
|
||||||
|
- `ShaderCompileResult` - 着色器编译结果
|
||||||
|
- `ShaderCompileMacro` - 着色器宏定义
|
||||||
|
- `InputElementDesc` - 输入元素描述
|
||||||
|
- `InputLayoutDesc` - 输入布局描述
|
||||||
|
- `VertexBufferBinding` - 顶点缓冲区绑定
|
||||||
|
- `TextureCopyLocation` - 纹理复制位置
|
||||||
|
- `DescriptorHandle` - 描述符句柄(通用类型)
|
||||||
|
- `GPUDescriptorHandle` - GPU描述符句柄
|
||||||
|
- `CPUDescriptorHandle` - CPU描述符句柄
|
||||||
|
- `ResourceBarrierDesc` - 资源屏障描述
|
||||||
|
- `SubresourceRange` - 子资源范围
|
||||||
|
- `TextureDesc` - 纹理描述
|
||||||
|
- `BufferDesc` - 缓冲区描述
|
||||||
|
- `RenderTargetDesc` - 渲染目标描述
|
||||||
|
- `DepthStencilDesc` - 深度模板描述
|
||||||
|
- `DescriptorHeapDesc` - 描述符堆描述
|
||||||
|
- `CommandQueueDesc` - 命令队列描述
|
||||||
|
- `CommandListDesc` - 命令列表描述
|
||||||
|
- `CommandAllocatorDesc` - 命令分配器描述
|
||||||
|
- `FenceDesc` - 围栏描述
|
||||||
|
- `QueryHeapDesc` - 查询堆描述
|
||||||
|
- `RootSignatureDesc` - 根签名描述
|
||||||
|
- `SamplerDesc` - 采样器描述
|
||||||
|
- `PipelineStateDesc` - 管线状态描述
|
||||||
|
- `SwapChainDesc` - 交换链描述
|
||||||
|
- `BlendStateDesc` - 混合状态描述
|
||||||
|
- `DepthStencilStateDesc` - 深度模板状态描述
|
||||||
|
- `RasterizerStateDesc` - 光栅化状态描述
|
||||||
|
- `ShaderBytecode` - 着色器字节码
|
||||||
|
- `ShaderBindingInfo` - 着色器绑定信息
|
||||||
|
- `RenderTargetViewDesc` - 渲染目标视图描述
|
||||||
|
- `DepthStencilViewDesc` - 深度模板视图描述
|
||||||
|
- `ShaderResourceViewDesc` - 着色器资源视图描述
|
||||||
|
- `UnorderedAccessViewDesc` - 无序访问视图描述
|
||||||
|
- `ConstantBufferViewDesc` - 常量缓冲区视图描述
|
||||||
|
- `FormatSupport` - 格式支持信息
|
||||||
|
|
||||||
|
### 2.3.2 核心接口定义
|
||||||
|
|
||||||
|
**任务 2.2:RHISystem.h - RHI系统入口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct RHISystemConfig {
|
||||||
|
void* nativeWindowHandle = nullptr; // HWND on Windows
|
||||||
|
uint32_t width = 1280;
|
||||||
|
uint32_t height = 720;
|
||||||
|
bool fullscreen = false;
|
||||||
|
uint32_t backBufferCount = 2;
|
||||||
|
bool enableDebugLayer = false;
|
||||||
|
bool enableGBV = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RHISystem {
|
||||||
|
public:
|
||||||
|
static RHISystem& Get();
|
||||||
|
|
||||||
|
bool Initialize(const RHISystemConfig& config);
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
IRHIDevice* GetDevice();
|
||||||
|
ISwapChain* GetSwapChain();
|
||||||
|
|
||||||
|
void BeginFrame();
|
||||||
|
void EndFrame();
|
||||||
|
|
||||||
|
// 窗口管理
|
||||||
|
void Resize(uint32_t width, uint32_t height);
|
||||||
|
void SetFullscreen(bool fullscreen);
|
||||||
|
bool IsFullscreen() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<IRHIDevice> m_device;
|
||||||
|
std::unique_ptr<ISwapChain> m_swapChain;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.3:RHIDevice.h - 抽象设备接口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct DeviceInfo {
|
||||||
|
String deviceName;
|
||||||
|
String driverVersion;
|
||||||
|
uint64_t dedicatedVideoMemory;
|
||||||
|
uint64_t dedicatedSystemMemory;
|
||||||
|
uint64_t sharedSystemMemory;
|
||||||
|
uint32_t vendorId;
|
||||||
|
uint32_t deviceId;
|
||||||
|
bool supportsRaytracing;
|
||||||
|
bool supportsMeshShaders;
|
||||||
|
bool supportsSamplerFeedback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRHIDevice {
|
||||||
|
public:
|
||||||
|
virtual ~IRHIDevice() = default;
|
||||||
|
|
||||||
|
// 资源创建
|
||||||
|
virtual ICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0;
|
||||||
|
virtual ICommandList* CreateCommandList(const CommandListDesc& desc) = 0;
|
||||||
|
virtual ICommandAllocator* CreateCommandAllocator(const CommandAllocatorDesc& desc) = 0;
|
||||||
|
virtual IFence* CreateFence(const FenceDesc& desc) = 0;
|
||||||
|
virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0;
|
||||||
|
virtual IQueryHeap* CreateQueryHeap(const QueryHeapDesc& desc) = 0;
|
||||||
|
virtual IRootSignature* CreateRootSignature(const RootSignatureDesc& desc) = 0;
|
||||||
|
virtual IPipelineState* CreatePipelineState(const PipelineStateDesc& desc) = 0;
|
||||||
|
virtual ISampler* CreateSampler(const SamplerDesc& desc) = 0;
|
||||||
|
virtual ITexture* CreateTexture(const TextureDesc& desc) = 0;
|
||||||
|
virtual IBuffer* CreateBuffer(const BufferDesc& desc) = 0;
|
||||||
|
virtual ISwapChain* CreateSwapChain(const SwapChainDesc& desc) = 0;
|
||||||
|
|
||||||
|
// 视图创建
|
||||||
|
virtual IRenderTargetView* CreateRenderTargetView(IResource* resource, const RenderTargetViewDesc& desc) = 0;
|
||||||
|
virtual IDepthStencilView* CreateDepthStencilView(IResource* resource, const DepthStencilViewDesc& desc) = 0;
|
||||||
|
virtual IShaderResourceView* CreateShaderResourceView(IResource* resource, const ShaderResourceViewDesc& desc) = 0;
|
||||||
|
virtual IUnorderedAccessView* CreateUnorderedAccessView(IResource* resource, const UnorderedAccessViewDesc& desc) = 0;
|
||||||
|
virtual IConstantBufferView* CreateConstantBufferView(IResource* resource, const ConstantBufferViewDesc& desc) = 0;
|
||||||
|
|
||||||
|
// 着色器编译
|
||||||
|
virtual IShader* CompileShader(const ShaderCompileDesc& desc) = 0;
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
virtual void GetDeviceInfo(DeviceInfo& info) const = 0;
|
||||||
|
virtual FormatSupport GetFormatSupport(Format format) const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.4:CommandQueue.h - 命令队列接口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class ICommandQueue {
|
||||||
|
public:
|
||||||
|
virtual ~ICommandQueue() = default;
|
||||||
|
|
||||||
|
virtual void ExecuteCommandLists(uint32_t count, ICommandList** lists) = 0;
|
||||||
|
virtual void Signal(IFence* fence, uint64_t value) = 0;
|
||||||
|
virtual void Wait(IFence* fence, uint64_t value) = 0;
|
||||||
|
virtual uint64_t GetCompletedValue() = 0;
|
||||||
|
virtual void WaitForIdle() = 0;
|
||||||
|
|
||||||
|
virtual CommandQueueType GetType() const = 0;
|
||||||
|
virtual uint64_t GetTimestampFrequency() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.5:CommandList.h - 命令列表接口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class ICommandList {
|
||||||
|
public:
|
||||||
|
virtual ~ICommandList() = default;
|
||||||
|
|
||||||
|
// 状态转换
|
||||||
|
virtual void TransitionBarrier(uint32_t count, const ResourceBarrierDesc* barriers) = 0;
|
||||||
|
virtual void UAVBarrier(IResource* resource = nullptr) = 0;
|
||||||
|
virtual void AliasBarrier(IResource* before, IResource* after) = 0;
|
||||||
|
|
||||||
|
// 渲染状态
|
||||||
|
virtual void SetPipelineState(IPipelineState* pso) = 0;
|
||||||
|
virtual void SetRootSignature(IRootSignature* signature) = 0;
|
||||||
|
virtual void SetViewport(const Viewport& viewport) = 0;
|
||||||
|
virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0;
|
||||||
|
virtual void SetScissorRect(const Rect& rect) = 0;
|
||||||
|
virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0;
|
||||||
|
virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0;
|
||||||
|
virtual void SetRenderTargets(uint32_t count, IResource** renderTargets, IResource* depthStencil) = 0;
|
||||||
|
|
||||||
|
// 绑定
|
||||||
|
virtual void SetVertexBuffer(uint32_t slot, IBuffer* buffer, uint32_t offset, uint32_t stride) = 0;
|
||||||
|
virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const VertexBufferBinding* bindings) = 0;
|
||||||
|
virtual void SetIndexBuffer(IBuffer* buffer, uint32_t offset, Format indexFormat) = 0;
|
||||||
|
virtual void SetConstantBuffer(uint32_t rootParameterIndex, IBuffer* buffer, uint32_t offset, uint32_t size) = 0;
|
||||||
|
virtual void SetShaderResource(uint32_t rootParameterIndex, IResource* resource) = 0;
|
||||||
|
virtual void SetUnorderedAccess(uint32_t rootParameterIndex, IResource* resource) = 0;
|
||||||
|
virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0;
|
||||||
|
virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0;
|
||||||
|
virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0;
|
||||||
|
|
||||||
|
// 渲染状态设置
|
||||||
|
virtual void SetStencilRef(uint8_t stencilRef) = 0;
|
||||||
|
virtual void SetBlendFactor(const float blendFactor[4]) = 0;
|
||||||
|
virtual void SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) = 0;
|
||||||
|
|
||||||
|
// 绘制
|
||||||
|
virtual void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) = 0;
|
||||||
|
virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0;
|
||||||
|
virtual void DrawInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
|
||||||
|
virtual void DrawIndexedInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
virtual void ClearRenderTargetView(IResource* renderTarget, const float color[4]) = 0;
|
||||||
|
virtual void ClearDepthStencilView(IResource* depthStencil, uint32_t clearFlags, float depth, uint8_t stencil) = 0;
|
||||||
|
virtual void ClearUnorderedAccessView(IResource* unorderedAccess, const float values[4]) = 0;
|
||||||
|
|
||||||
|
// 复制
|
||||||
|
virtual void CopyResource(IResource* dst, IResource* src) = 0;
|
||||||
|
virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, IBuffer* src, uint64_t srcOffset, uint64_t size) = 0;
|
||||||
|
virtual void CopyTexture(ITexture* dst, const TextureCopyLocation& dstLocation, ITexture* src, const TextureCopyLocation& srcLocation) = 0;
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
virtual void BeginQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0;
|
||||||
|
virtual void EndQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0;
|
||||||
|
virtual void ResolveQuery(IQueryHeap* queryHeap, QueryType type, uint32_t startIndex, uint32_t count, IBuffer* resultBuffer, uint64_t resultOffset) = 0;
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
virtual void Close() = 0;
|
||||||
|
virtual void Reset(ICommandAllocator* allocator) = 0;
|
||||||
|
|
||||||
|
// 计算着色器
|
||||||
|
virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0;
|
||||||
|
virtual void DispatchIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
|
||||||
|
|
||||||
|
// Bundle (用于命令复用)
|
||||||
|
virtual void ExecuteBundle(ICommandList* bundle) = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.6:其他核心接口**
|
||||||
|
|
||||||
|
- `Resource.h` - 资源基类接口(所有资源的共同基类)
|
||||||
|
- `ResourceView.h` - 资源视图基类接口
|
||||||
|
- `RenderTargetView.h` - 渲染目标视图接口
|
||||||
|
- `DepthStencilView.h` - 深度模板视图接口
|
||||||
|
- `ShaderResourceView.h` - 着色器资源视图接口
|
||||||
|
- `UnorderedAccessView.h` - 无序访问视图接口
|
||||||
|
- `ConstantBufferView.h` - 常量缓冲区视图接口
|
||||||
|
- `CommandAllocator.h` - 命令分配器接口
|
||||||
|
```cpp
|
||||||
|
class ICommandAllocator {
|
||||||
|
public:
|
||||||
|
virtual ~ICommandAllocator() = default;
|
||||||
|
virtual void Reset() = 0;
|
||||||
|
virtual bool IsReady() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `Fence.h` - 同步围栏接口
|
||||||
|
```cpp
|
||||||
|
class IFence {
|
||||||
|
public:
|
||||||
|
virtual ~IFence() = default;
|
||||||
|
virtual void Signal(uint64_t value) = 0;
|
||||||
|
virtual void Wait(uint64_t value) = 0;
|
||||||
|
virtual uint64_t GetCompletedValue() = 0;
|
||||||
|
virtual void* GetEventHandle() = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `DescriptorHeap.h` - 描述符堆接口
|
||||||
|
```cpp
|
||||||
|
class IDescriptorHeap {
|
||||||
|
public:
|
||||||
|
virtual ~IDescriptorHeap() = default;
|
||||||
|
virtual CPUDescriptorHandle GetCPUDescriptorHandle(uint32_t index) = 0;
|
||||||
|
virtual GPUDescriptorHandle GetGPUDescriptorHandle(uint32_t index) = 0;
|
||||||
|
virtual uint32_t GetDescriptorCount() const = 0;
|
||||||
|
virtual DescriptorType GetType() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `QueryHeap.h` - 查询堆接口
|
||||||
|
```cpp
|
||||||
|
class IQueryHeap {
|
||||||
|
public:
|
||||||
|
virtual ~IQueryHeap() = default;
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
virtual QueryType GetType() const = 0;
|
||||||
|
virtual uint32_t GetCount() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `RootSignature.h` - 根签名接口
|
||||||
|
```cpp
|
||||||
|
class IRootSignature {
|
||||||
|
public:
|
||||||
|
virtual ~IRootSignature() = default;
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
virtual uint32_t GetParameterCount() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `PipelineState.h` - 管线状态接口
|
||||||
|
```cpp
|
||||||
|
class IPipelineState {
|
||||||
|
public:
|
||||||
|
virtual ~IPipelineState() = default;
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
virtual PipelineType GetType() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `Sampler.h` - 采样器接口
|
||||||
|
```cpp
|
||||||
|
class ISampler {
|
||||||
|
public:
|
||||||
|
virtual ~ISampler() = default;
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `SwapChain.h` - 交换链接口
|
||||||
|
```cpp
|
||||||
|
class ISwapChain {
|
||||||
|
public:
|
||||||
|
virtual ~ISwapChain() = default;
|
||||||
|
|
||||||
|
virtual uint32_t GetCurrentBackBufferIndex() = 0;
|
||||||
|
virtual IResource* GetBackBuffer(uint32_t index) = 0;
|
||||||
|
virtual void Present(uint32_t syncInterval, PresentFlags flags) = 0;
|
||||||
|
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
||||||
|
virtual void SetFullscreen(bool fullscreen) = 0;
|
||||||
|
virtual bool IsFullscreen() const = 0;
|
||||||
|
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `Texture.h` - 纹理资源接口
|
||||||
|
```cpp
|
||||||
|
class ITexture : public IResource {
|
||||||
|
public:
|
||||||
|
virtual uint32_t GetWidth() const = 0;
|
||||||
|
virtual uint32_t GetHeight() const = 0;
|
||||||
|
virtual uint32_t GetDepth() const = 0;
|
||||||
|
virtual uint32_t GetMipLevels() const = 0;
|
||||||
|
virtual uint32_t GetArraySize() const = 0;
|
||||||
|
virtual Format GetFormat() const = 0;
|
||||||
|
virtual TextureType GetTextureType() const = 0;
|
||||||
|
|
||||||
|
virtual IShaderResourceView* GetOrCreateSRV() = 0;
|
||||||
|
virtual IRenderTargetView* GetOrCreateRTV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
|
||||||
|
virtual IDepthStencilView* GetOrCreateDSV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
|
||||||
|
virtual IUnorderedAccessView* GetOrCreateUAV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `Buffer.h` - 缓冲区资源接口
|
||||||
|
```cpp
|
||||||
|
class IBuffer : public IResource {
|
||||||
|
public:
|
||||||
|
virtual uint64_t GetSize() const = 0;
|
||||||
|
virtual uint32_t GetStride() const = 0;
|
||||||
|
virtual BufferType GetBufferType() const = 0;
|
||||||
|
|
||||||
|
virtual IConstantBufferView* GetOrCreateCBV() = 0;
|
||||||
|
virtual IShaderResourceView* GetOrCreateSRV() = 0;
|
||||||
|
virtual IUnorderedAccessView* GetOrCreateUAV() = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `Shader.h` - 着色器接口
|
||||||
|
```cpp
|
||||||
|
class IShader {
|
||||||
|
public:
|
||||||
|
virtual ~IShader() = default;
|
||||||
|
|
||||||
|
virtual const void* GetBytecode() const = 0;
|
||||||
|
virtual size_t GetBytecodeSize() const = 0;
|
||||||
|
virtual ShaderType GetType() const = 0;
|
||||||
|
|
||||||
|
virtual const InputLayoutDesc& GetInputLayout() const = 0;
|
||||||
|
virtual const ShaderBindingInfo& GetBindingInfo() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `RenderTarget.h` - 渲染目标接口
|
||||||
|
```cpp
|
||||||
|
class IRenderTarget {
|
||||||
|
public:
|
||||||
|
virtual ~IRenderTarget() = default;
|
||||||
|
|
||||||
|
virtual ITexture* GetTexture() = 0;
|
||||||
|
virtual IRenderTargetView* GetRTV() = 0;
|
||||||
|
virtual uint32_t GetWidth() const = 0;
|
||||||
|
virtual uint32_t GetHeight() const = 0;
|
||||||
|
virtual Format GetFormat() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- `DepthStencil.h` - 深度模板接口
|
||||||
|
```cpp
|
||||||
|
class IDepthStencil {
|
||||||
|
public:
|
||||||
|
virtual ~IDepthStencil() = default;
|
||||||
|
|
||||||
|
virtual ITexture* GetTexture() = 0;
|
||||||
|
virtual IDepthStencilView* GetDSV() = 0;
|
||||||
|
virtual IShaderResourceView* GetSRV() = 0;
|
||||||
|
virtual uint32_t GetWidth() const = 0;
|
||||||
|
virtual uint32_t GetHeight() const = 0;
|
||||||
|
virtual Format GetFormat() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.7:Resource.h - 资源基类接口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class IResource {
|
||||||
|
public:
|
||||||
|
virtual ~IResource() = default;
|
||||||
|
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
virtual ResourceStates GetState() const = 0;
|
||||||
|
virtual void SetState(ResourceStates state) = 0;
|
||||||
|
|
||||||
|
virtual uint64_t GetGPUAddress() const = 0;
|
||||||
|
virtual size_t GetSize() const = 0;
|
||||||
|
|
||||||
|
virtual const String& GetName() const = 0;
|
||||||
|
virtual void SetName(const String& name) = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**任务 2.8:ResourceView.h - 资源视图基类接口**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class IResourceView {
|
||||||
|
public:
|
||||||
|
virtual ~IResourceView() = default;
|
||||||
|
virtual void* GetNativeHandle() const = 0;
|
||||||
|
virtual IResource* GetResource() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.3.3 D3D12 后端实现
|
||||||
|
|
||||||
|
**任务 2.9:D3D12Common.h - 公共定义**
|
||||||
|
|
||||||
|
D3D12相关的公共定义和辅助函数:
|
||||||
|
- 格式转换映射
|
||||||
|
- 描述符大小计算
|
||||||
|
- 资源状态转换
|
||||||
|
- 辅助工具函数
|
||||||
|
|
||||||
|
**任务 2.10:D3D12Device - 设备实现**
|
||||||
|
|
||||||
|
实现 `D3D12Device` 类:
|
||||||
|
- ID3D12Device 封装
|
||||||
|
- IDXGIFactory 创建与管理
|
||||||
|
- 所有资源创建接口实现
|
||||||
|
- 适配器信息查询
|
||||||
|
- 功能级别支持检测
|
||||||
|
- 内存信息查询
|
||||||
|
- 设备移除与恢复处理
|
||||||
|
|
||||||
|
**任务 2.11:D3D12CommandQueue - 命令队列实现**
|
||||||
|
|
||||||
|
实现 `D3D12CommandQueue` 类:
|
||||||
|
- ID3D12CommandQueue 封装
|
||||||
|
- 命令列表执行
|
||||||
|
- 围栏同步
|
||||||
|
- 时间戳频率查询
|
||||||
|
|
||||||
|
**任务 2.12:D3D12CommandList - 命令列表实现**
|
||||||
|
|
||||||
|
实现 `D3D12CommandList` 类:
|
||||||
|
- ID3D12GraphicsCommandList 封装
|
||||||
|
- 所有渲染命令实现
|
||||||
|
- 状态追踪与验证
|
||||||
|
- 资源追踪
|
||||||
|
|
||||||
|
**任务 2.13:D3D12CommandAllocator - 命令分配器实现**
|
||||||
|
|
||||||
|
实现 `D3D12CommandAllocator` 类:
|
||||||
|
- ID3D12CommandAllocator 封装
|
||||||
|
- 重置管理
|
||||||
|
|
||||||
|
**任务 2.14:D3D12Fence - 围栏实现**
|
||||||
|
|
||||||
|
实现 `D3D12Fence` 类:
|
||||||
|
- ID3D12Fence 封装
|
||||||
|
- CPU/GPU同步
|
||||||
|
- 事件句柄管理
|
||||||
|
|
||||||
|
**任务 2.15:D3D12DescriptorHeap - 描述符堆实现**
|
||||||
|
|
||||||
|
实现 `D3D12DescriptorHeap` 类:
|
||||||
|
- ID3D12DescriptorHeap 封装
|
||||||
|
- CPU/GPU描述符句柄管理
|
||||||
|
- 描述符分配/释放
|
||||||
|
- 堆增量大小计算
|
||||||
|
|
||||||
|
**任务 2.16:D3D12RootSignature - 根签名实现**
|
||||||
|
|
||||||
|
实现 `D3D12RootSignature` 类:
|
||||||
|
- ID3D12RootSignature 封装
|
||||||
|
- 根参数配置
|
||||||
|
- 描述符表布局
|
||||||
|
- 静态采样器
|
||||||
|
|
||||||
|
**任务 2.17:D3D12PipelineState - 管线状态实现**
|
||||||
|
|
||||||
|
实现 `D3D12PipelineState` 类:
|
||||||
|
- ID3D12PipelineState 封装
|
||||||
|
- 图形管线描述构建
|
||||||
|
- 计算管线描述构建
|
||||||
|
- 混合状态
|
||||||
|
- 深度模板状态
|
||||||
|
- 输入布局
|
||||||
|
- 顶点/像素着色器绑定
|
||||||
|
|
||||||
|
**任务 2.18:D3D12Sampler - 采样器实现**
|
||||||
|
|
||||||
|
实现 `D3D12Sampler` 类:
|
||||||
|
- D3D12_SAMPLER_DESC 封装
|
||||||
|
- 静态采样器支持
|
||||||
|
|
||||||
|
**任务 2.19:D3D12QueryHeap - 查询堆实现**
|
||||||
|
|
||||||
|
实现 `D3D12QueryHeap` 类:
|
||||||
|
- ID3D12QueryHeap 封装
|
||||||
|
- 时间戳查询
|
||||||
|
- 遮挡查询
|
||||||
|
- 流水线统计
|
||||||
|
|
||||||
|
**任务 2.20:D3D12SwapChain - 交换链实现**
|
||||||
|
|
||||||
|
实现 `D3D12SwapChain` 类:
|
||||||
|
- IDXGISwapChain3 封装
|
||||||
|
- 帧缓冲管理
|
||||||
|
- 呈现模式配置
|
||||||
|
- 完整屏幕支持
|
||||||
|
|
||||||
|
**任务 2.21:D3D12Texture - 纹理实现**
|
||||||
|
|
||||||
|
实现 `D3D12Texture` 类:
|
||||||
|
- ID3D12Resource 封装
|
||||||
|
- 纹理描述
|
||||||
|
- 子资源管理
|
||||||
|
- 视图创建(SRV, RTV, DSV, UAV)
|
||||||
|
- 状态管理
|
||||||
|
|
||||||
|
**任务 2.22:D3D12Buffer - 缓冲区实现**
|
||||||
|
|
||||||
|
实现 `D3D12Buffer` 类:
|
||||||
|
- ID3D12Resource 封装
|
||||||
|
- 缓冲区描述
|
||||||
|
- 视图创建(SRV, CBV, UAV)
|
||||||
|
- 上传堆管理
|
||||||
|
- 默认堆管理
|
||||||
|
|
||||||
|
**任务 2.23:D3D12Shader - 着色器实现**
|
||||||
|
|
||||||
|
实现 `D3D12Shader` 类:
|
||||||
|
- 着色器字节码管理
|
||||||
|
- 反射数据提取
|
||||||
|
- 输入布局构建
|
||||||
|
|
||||||
|
**任务 2.24:D3D12RenderTargetView - 渲染目标视图实现**
|
||||||
|
|
||||||
|
实现 `D3D12RenderTargetView` 类:
|
||||||
|
- ID3D12RenderTargetView 封装
|
||||||
|
- 描述符创建与管理
|
||||||
|
|
||||||
|
**任务 2.25:D3D12DepthStencilView - 深度模板视图实现**
|
||||||
|
|
||||||
|
实现 `D3D12DepthStencilView` 类:
|
||||||
|
- ID3D12DepthStencilView 封装
|
||||||
|
- 描述符创建与管理
|
||||||
|
|
||||||
|
**任务 2.26:D3D12ShaderResourceView - 着色器资源视图实现**
|
||||||
|
|
||||||
|
实现 `D3D12ShaderResourceView` 类:
|
||||||
|
- ID3D12ShaderResourceView 封装
|
||||||
|
- 描述符创建与管理
|
||||||
|
|
||||||
|
**任务 2.27:D3D12UnorderedAccessView - 无序访问视图实现**
|
||||||
|
|
||||||
|
实现 `D3D12UnorderedAccessView` 类:
|
||||||
|
- ID3D12UnorderedAccessView 封装
|
||||||
|
- 描述符创建与管理
|
||||||
|
|
||||||
|
**任务 2.28:D3D12ConstantBufferView - 常量缓冲区视图实现**
|
||||||
|
|
||||||
|
实现 `D3D12ConstantBufferView` 类:
|
||||||
|
- ID3D12ConstantBufferView 封装
|
||||||
|
- 描述符创建与管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.4 实现顺序
|
||||||
|
|
||||||
|
```
|
||||||
|
阶段 2.1: 基础枚举与类型 (1天)
|
||||||
|
├── 2.1.1 Enums.h
|
||||||
|
└── 2.1.2 Types.h (通用类型定义)
|
||||||
|
|
||||||
|
阶段 2.2: 核心接口定义 (3天)
|
||||||
|
├── 2.2.1 RHISystem.h
|
||||||
|
├── 2.2.2 RHIDevice.h
|
||||||
|
├── 2.2.3 Resource.h (资源基类)
|
||||||
|
├── 2.2.4 ResourceView.h (视图基类)
|
||||||
|
├── 2.2.5 CommandQueue.h
|
||||||
|
├── 2.2.6 CommandList.h
|
||||||
|
└── 2.2.7 其他接口文件
|
||||||
|
|
||||||
|
阶段 2.3: D3D12 后端实现 (7天)
|
||||||
|
├── 2.3.1 D3D12Common.h
|
||||||
|
├── 2.3.2 D3D12Device
|
||||||
|
├── 2.3.3 D3D12Resource / D3D12Texture / D3D12Buffer
|
||||||
|
├── 2.3.4 D3D12CommandQueue
|
||||||
|
├── 2.3.5 D3D12CommandList
|
||||||
|
├── 2.3.6 D3D12CommandAllocator
|
||||||
|
├── 2.3.7 D3D12Fence
|
||||||
|
├── 2.3.8 D3D12DescriptorHeap
|
||||||
|
├── 2.3.9 D3D12RootSignature
|
||||||
|
├── 2.3.10 D3D12PipelineState
|
||||||
|
├── 2.3.11 D3D12Sampler
|
||||||
|
├── 2.3.12 D3D12QueryHeap
|
||||||
|
├── 2.3.13 D3D12SwapChain
|
||||||
|
├── 2.3.14 D3D12Shader
|
||||||
|
├── 2.3.15 D3D12RenderTargetView
|
||||||
|
├── 2.3.16 D3D12DepthStencilView
|
||||||
|
├── 2.3.17 D3D12ShaderResourceView
|
||||||
|
├── 2.3.18 D3D12UnorderedAccessView
|
||||||
|
└── 2.3.19 D3D12ConstantBufferView
|
||||||
|
|
||||||
|
阶段 2.4: 集成测试 (1天)
|
||||||
|
├── 窗口创建与交换链关联
|
||||||
|
├── 渲染循环基本框架
|
||||||
|
└── 简单的清屏测试
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.5 验收标准
|
||||||
|
|
||||||
|
1. **编译通过**:所有头文件和实现文件能够无错误编译
|
||||||
|
2. **接口完整**:所有定义的接口都有D3D12实现
|
||||||
|
3. **功能验证**:
|
||||||
|
- 能够创建窗口并初始化D3D12设备
|
||||||
|
- 能够创建命令队列和命令列表
|
||||||
|
- 能够执行基本的渲染命令(清屏)
|
||||||
|
- 能够处理窗口消息和呈现
|
||||||
|
4. **代码质量**:
|
||||||
|
- 遵循编码规范
|
||||||
|
- 必要的注释和文档
|
||||||
|
- 错误处理完善
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.6 关键技术点
|
||||||
|
|
||||||
|
### 2.6.1 资源状态管理
|
||||||
|
|
||||||
|
D3D12要求严格的状态管理:
|
||||||
|
- 资源必须处于正确的状态才能使用
|
||||||
|
- 状态转换通过 `TransitionBarrier`
|
||||||
|
- 常用状态:`D3D12_RESOURCE_STATE_GENERIC_READ`, `D3D12_RESOURCE_STATE_RENDER_TARGET`, `D3D12_RESOURCE_STATE_DEPTH_WRITE` 等
|
||||||
|
|
||||||
|
### 2.6.2 描述符管理
|
||||||
|
|
||||||
|
- 描述符堆类型:CBV/SRV/UAV, Sampler, RTV, DSV
|
||||||
|
- GPU可见描述符堆用于渲染
|
||||||
|
- CPU可见描述符堆用于描述符拷贝
|
||||||
|
- 描述符递增大小计算
|
||||||
|
|
||||||
|
### 2.6.3 根签名设计
|
||||||
|
|
||||||
|
- 根参数类型:根常量、根描述符、根描述符表
|
||||||
|
- 描述符表:描述符数组
|
||||||
|
- 静态采样器:不可变的采样器配置
|
||||||
|
|
||||||
|
### 2.6.4 管线状态对象
|
||||||
|
|
||||||
|
- 图形管线:混合、深度、模板、光栅化、输入布局、顶点/像素/几何/ Hull/Domain着色器
|
||||||
|
- 计算管线:根签名、CS着色器
|
||||||
|
|
||||||
|
### 2.6.5 视图接口设计
|
||||||
|
|
||||||
|
- 每种视图类型(RTV/DSV/SRV/UAV/CBV)都有独立接口
|
||||||
|
- 视图持有对底层资源的引用
|
||||||
|
- 视图描述符确定资源的解释方式
|
||||||
|
|
||||||
|
### 2.6.6 着色器编译
|
||||||
|
|
||||||
|
- 使用D3DCompiler API或dxc编译HLSL
|
||||||
|
- 支持着色器反射获取输入布局和资源绑定信息
|
||||||
|
- 支持着色器宏定义和include处理
|
||||||
|
|
||||||
|
### 2.6.7 跨平台抽象设计原则
|
||||||
|
|
||||||
|
- 所有接口使用抽象类型,不暴露D3D12特定类型
|
||||||
|
- GPUDescriptorHandle/CPUDescriptorHandle 作为通用句柄类型
|
||||||
|
- 资源状态使用统一的ResourceStates枚举
|
||||||
|
- 创建描述符结构体独立于特定API
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2.7 后续阶段依赖
|
||||||
|
|
||||||
|
- 第三阶段:渲染管线(RenderPipeline)需要RHI作为基础
|
||||||
|
- 材质系统需要RHI的Shader和PipelineState
|
||||||
|
- 场景渲染需要CommandList提交绘制命令
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RHIDefines.h"
|
|
||||||
#include "IRHIResources.h"
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class IResource {
|
|
||||||
public:
|
|
||||||
virtual ~IResource() = default;
|
|
||||||
virtual void* GetNativeResource() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandList {
|
|
||||||
public:
|
|
||||||
virtual ~ICommandList() = default;
|
|
||||||
|
|
||||||
virtual void Reset(void* allocator) = 0;
|
|
||||||
virtual void Close() = 0;
|
|
||||||
virtual void SetPipelineState(IPipelineState* pso) = 0;
|
|
||||||
virtual void SetRootSignature(IRootSignature* signature) = 0;
|
|
||||||
virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0;
|
|
||||||
virtual void SetVertexBuffer(uint32_t slot, IResource* buffer, uint32_t offset = 0, uint32_t stride = 0) = 0;
|
|
||||||
virtual void SetIndexBuffer(IResource* buffer, uint32_t offset = 0) = 0;
|
|
||||||
virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0;
|
|
||||||
virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0;
|
|
||||||
virtual void SetGraphicsRootConstantBufferView(uint32_t slot, IResource* buffer) = 0;
|
|
||||||
virtual void SetGraphicsRootConstantBufferViewCBV(uint32_t slot, void* nativeResource) = 0;
|
|
||||||
virtual void SetGraphicsRoot32BitConstants(uint32_t rootParameterIndex, uint32_t num32BitValues, const void* data, uint32_t destOffsetIn32BitValues) = 0;
|
|
||||||
virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0;
|
|
||||||
virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) = 0;
|
|
||||||
virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0;
|
|
||||||
virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0;
|
|
||||||
virtual void SetViewports(const Viewport* viewports, uint32_t count) = 0;
|
|
||||||
virtual void SetScissorRects(const Rect* rects, uint32_t count) = 0;
|
|
||||||
virtual void SetRenderTargets(void** targets, uint32_t count, void* depthStencil) = 0;
|
|
||||||
virtual void ClearRenderTargetView(void* target, const float color[4]) = 0;
|
|
||||||
virtual void ClearDepthStencilView(void* depth, float depthValue, uint8_t stencil) = 0;
|
|
||||||
virtual void CopyResource(IResource* dst, const IResource* src) = 0;
|
|
||||||
virtual void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) = 0;
|
|
||||||
virtual void ResourceBarrier(IResource* resource, ResourceStateFlag before, ResourceStateFlag after) = 0;
|
|
||||||
virtual void* GetNativeCommandList() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RHIDefines.h"
|
|
||||||
#include "ICommandList.h"
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
struct ShaderBytecode {
|
|
||||||
const void* bytecode = nullptr;
|
|
||||||
uint64_t size = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InputElementDesc {
|
|
||||||
const char* semanticName = nullptr;
|
|
||||||
uint32_t semanticIndex = 0;
|
|
||||||
Format format = Format::Unknown;
|
|
||||||
uint32_t inputSlot = 0;
|
|
||||||
uint32_t alignedByteOffset = 0;
|
|
||||||
uint32_t inputSlotClass = 0; // 0 = per-vertex
|
|
||||||
uint32_t instanceDataStepRate = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InputLayoutDesc {
|
|
||||||
const InputElementDesc* elements = nullptr;
|
|
||||||
uint32_t elementCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class PrimitiveTopologyType {
|
|
||||||
Undefined,
|
|
||||||
Point,
|
|
||||||
Line,
|
|
||||||
Triangle,
|
|
||||||
Patch
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BlendFactor {
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
SrcColor,
|
|
||||||
InvSrcColor,
|
|
||||||
SrcAlpha,
|
|
||||||
InvSrcAlpha,
|
|
||||||
DestAlpha,
|
|
||||||
InvDestAlpha,
|
|
||||||
DestColor,
|
|
||||||
InvDestColor
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BlendOp {
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
ReverseSubtract,
|
|
||||||
Min,
|
|
||||||
Max
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ComparisonFunc {
|
|
||||||
Never,
|
|
||||||
Less,
|
|
||||||
Equal,
|
|
||||||
LessEqual,
|
|
||||||
Greater,
|
|
||||||
NotEqual,
|
|
||||||
GreaterEqual,
|
|
||||||
Always
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CullMode {
|
|
||||||
None,
|
|
||||||
Front,
|
|
||||||
Back
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FillMode {
|
|
||||||
Wireframe,
|
|
||||||
Solid
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlendState {
|
|
||||||
bool enable = false;
|
|
||||||
BlendFactor srcBlend = BlendFactor::SrcAlpha;
|
|
||||||
BlendFactor destBlend = BlendFactor::InvSrcAlpha;
|
|
||||||
BlendOp blendOp = BlendOp::Add;
|
|
||||||
BlendFactor srcBlendAlpha = BlendFactor::One;
|
|
||||||
BlendFactor destBlendAlpha = BlendFactor::Zero;
|
|
||||||
BlendOp blendOpAlpha = BlendOp::Add;
|
|
||||||
uint8_t renderTargetWriteMask = 0xF;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DepthStencilState {
|
|
||||||
bool depthEnable = true;
|
|
||||||
bool stencilEnable = false;
|
|
||||||
ComparisonFunc depthFunc = ComparisonFunc::Less;
|
|
||||||
uint8_t depthWriteMask = 0xFF;
|
|
||||||
uint8_t stencilReadMask = 0xFF;
|
|
||||||
uint8_t stencilWriteMask = 0xFF;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RasterizerState {
|
|
||||||
FillMode fillMode = FillMode::Solid;
|
|
||||||
CullMode cullMode = CullMode::Back;
|
|
||||||
bool frontCounterClockwise = true;
|
|
||||||
int32_t depthBias = 0;
|
|
||||||
float depthBiasClamp = 0.0f;
|
|
||||||
float slopeScaledDepthBias = 0.0f;
|
|
||||||
bool depthClipEnable = true;
|
|
||||||
bool scissorEnable = false;
|
|
||||||
bool multisampleEnable = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RenderState {
|
|
||||||
BlendState blendState;
|
|
||||||
DepthStencilState depthStencilState;
|
|
||||||
RasterizerState rasterizerState;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PipelineDesc {
|
|
||||||
IRootSignature* rootSignature = nullptr;
|
|
||||||
ShaderBytecode vertexShader;
|
|
||||||
ShaderBytecode pixelShader;
|
|
||||||
ShaderBytecode geometryShader;
|
|
||||||
ShaderBytecode computeShader;
|
|
||||||
RenderState renderState;
|
|
||||||
InputLayoutDesc inputLayout;
|
|
||||||
PrimitiveTopologyType topologyType = PrimitiveTopologyType::Triangle;
|
|
||||||
uint32_t numRenderTargets = 1;
|
|
||||||
Format rtvFormats[8] = { Format::Unknown };
|
|
||||||
Format dsvFormat = Format::Unknown;
|
|
||||||
SampleCount sampleCount = SampleCount::Count1;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IRHIDevice {
|
|
||||||
public:
|
|
||||||
virtual ~IRHIDevice() = default;
|
|
||||||
|
|
||||||
virtual GraphicsAPI GetAPI() const = 0;
|
|
||||||
virtual const char* GetAPIName() const = 0;
|
|
||||||
|
|
||||||
virtual bool Initialize(void* windowHandle, uint32_t width, uint32_t height) = 0;
|
|
||||||
virtual void Shutdown() = 0;
|
|
||||||
|
|
||||||
virtual bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) = 0;
|
|
||||||
virtual bool CreateCommandAllocator(ICommandAllocator** allocator) = 0;
|
|
||||||
virtual bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) = 0;
|
|
||||||
virtual bool CreateFence(IFence** fence) = 0;
|
|
||||||
|
|
||||||
virtual bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) = 0;
|
|
||||||
|
|
||||||
virtual bool CreateRootSignature(IRootSignature** signature, const RootSignatureDesc& desc) = 0;
|
|
||||||
virtual bool CreatePipelineState(IPipelineState** pso, const PipelineDesc& desc) = 0;
|
|
||||||
|
|
||||||
virtual bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) = 0;
|
|
||||||
|
|
||||||
virtual ICommandQueue* GetCommandQueue() = 0;
|
|
||||||
virtual void* GetNativeDevice() const = 0;
|
|
||||||
virtual void* GetNativeAdapter() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RHIDefines.h"
|
|
||||||
#include <unknwn.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class ICommandQueue {
|
|
||||||
public:
|
|
||||||
virtual ~ICommandQueue() = default;
|
|
||||||
|
|
||||||
virtual void ExecuteCommandLists(void** lists, uint32_t count) = 0;
|
|
||||||
virtual void Signal(void* fence, uint64_t value) = 0;
|
|
||||||
virtual void Wait(void* fence, uint64_t value) = 0;
|
|
||||||
virtual uint64_t GetTimestampFrequency() const = 0;
|
|
||||||
virtual IUnknown* GetNativeQueue() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandAllocator {
|
|
||||||
public:
|
|
||||||
virtual ~ICommandAllocator() = default;
|
|
||||||
virtual void Reset() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IFence {
|
|
||||||
public:
|
|
||||||
virtual ~IFence() = default;
|
|
||||||
virtual uint64_t GetCompletedValue() const = 0;
|
|
||||||
virtual void Signal(uint64_t value) = 0;
|
|
||||||
virtual void Wait(uint64_t value) = 0;
|
|
||||||
virtual void Wait(uint64_t value, uint64_t timeoutMs) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDescriptorHeap {
|
|
||||||
public:
|
|
||||||
virtual ~IDescriptorHeap() = default;
|
|
||||||
virtual DescriptorHeapType GetType() const = 0;
|
|
||||||
virtual uint32_t GetDescriptorCount() const = 0;
|
|
||||||
virtual void* GetCPUDescriptorHandle(uint32_t index) const = 0;
|
|
||||||
virtual uint64_t GetGPUDescriptorHandle(uint32_t index) const = 0;
|
|
||||||
virtual void SetName(const char* name) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISwapChain {
|
|
||||||
public:
|
|
||||||
virtual ~ISwapChain() = default;
|
|
||||||
virtual bool Initialize(const SwapChainDesc& desc, void* windowHandle) = 0;
|
|
||||||
virtual void Shutdown() = 0;
|
|
||||||
virtual bool Present() = 0;
|
|
||||||
virtual bool Resize(uint32_t width, uint32_t height) = 0;
|
|
||||||
virtual uint32_t GetCurrentBufferIndex() const = 0;
|
|
||||||
virtual void* GetBuffer(uint32_t index) = 0;
|
|
||||||
virtual void* GetCurrentRenderTarget() = 0;
|
|
||||||
virtual void* GetDepthStencil() = 0;
|
|
||||||
virtual void SetFullscreen(bool fullscreen) = 0;
|
|
||||||
virtual bool IsFullscreen() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class RootParameterType {
|
|
||||||
DescriptorTable,
|
|
||||||
Constants,
|
|
||||||
CBV,
|
|
||||||
SRV,
|
|
||||||
UAV,
|
|
||||||
Sampler
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootParameter {
|
|
||||||
RootParameterType type;
|
|
||||||
uint32_t shaderRegister = 0;
|
|
||||||
uint32_t registerSpace = 0;
|
|
||||||
uint32_t num32BitValues = 4;
|
|
||||||
ShaderVisibility visibility = ShaderVisibility::All;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootSignatureDesc {
|
|
||||||
RootParameter* parameters = nullptr;
|
|
||||||
uint32_t parameterCount = 0;
|
|
||||||
uint32_t flags = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IRootSignature {
|
|
||||||
public:
|
|
||||||
virtual ~IRootSignature() = default;
|
|
||||||
virtual bool Initialize(const RootSignatureDesc& desc) = 0;
|
|
||||||
virtual void SetName(const char* name) = 0;
|
|
||||||
virtual void* GetNativeRootSignature() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IPipelineState {
|
|
||||||
public:
|
|
||||||
virtual ~IPipelineState() = default;
|
|
||||||
virtual void SetName(const char* name) = 0;
|
|
||||||
virtual void* GetNativePipelineState() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RHIDefines.h"
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class IShaderResourceView {
|
|
||||||
public:
|
|
||||||
virtual ~IShaderResourceView() = default;
|
|
||||||
virtual void* GetNativeSRV() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IRenderTargetView {
|
|
||||||
public:
|
|
||||||
virtual ~IRenderTargetView() = default;
|
|
||||||
virtual void* GetNativeRTV() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDepthStencilView {
|
|
||||||
public:
|
|
||||||
virtual ~IDepthStencilView() = default;
|
|
||||||
virtual void* GetNativeDSV() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <dxgi1_4.h>
|
|
||||||
#include <d3d12.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
enum class Format : uint32_t {
|
|
||||||
Unknown = 0,
|
|
||||||
R8_UNorm = 61,
|
|
||||||
R8G8_UNorm = 49,
|
|
||||||
R8G8B8A8_UNorm = 28,
|
|
||||||
R16G16B16A16_Float = 10,
|
|
||||||
R32G32B32A32_Float = 2,
|
|
||||||
R16_Float = 54,
|
|
||||||
R32_Float = 41,
|
|
||||||
D16_UNorm = 55,
|
|
||||||
D24_UNorm_S8_UInt = 45,
|
|
||||||
D32_Float = 40,
|
|
||||||
BC1_UNorm = 71,
|
|
||||||
BC2_UNorm = 74,
|
|
||||||
BC3_UNorm = 77,
|
|
||||||
BC4_UNorm = 80,
|
|
||||||
BC5_UNorm = 83,
|
|
||||||
BC6H_UF16 = 95,
|
|
||||||
BC7_UNorm = 98
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class PrimitiveTopology : uint8_t {
|
|
||||||
Undefined = 0,
|
|
||||||
PointList = 1,
|
|
||||||
LineList = 2,
|
|
||||||
LineStrip = 3,
|
|
||||||
TriangleList = 4,
|
|
||||||
TriangleStrip = 5,
|
|
||||||
LineListAdj = 10,
|
|
||||||
LineStripAdj = 11,
|
|
||||||
TriangleListAdj = 12,
|
|
||||||
TriangleStripAdj = 13,
|
|
||||||
PatchList = 33
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class GraphicsAPI : uint8_t {
|
|
||||||
Unknown,
|
|
||||||
Direct3D11,
|
|
||||||
Direct3D12,
|
|
||||||
Vulkan,
|
|
||||||
Metal,
|
|
||||||
OpenGL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CommandListType : uint8_t {
|
|
||||||
Direct,
|
|
||||||
Compute,
|
|
||||||
Copy,
|
|
||||||
Bundle
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ShaderVisibility : uint8_t {
|
|
||||||
All = 0,
|
|
||||||
Vertex = 1,
|
|
||||||
Hull = 2,
|
|
||||||
Domain = 3,
|
|
||||||
Geometry = 4,
|
|
||||||
Pixel = 5,
|
|
||||||
Amplification = 6,
|
|
||||||
Mesh = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class DescriptorHeapType : uint8_t {
|
|
||||||
CBV_SRV_UAV,
|
|
||||||
Sampler,
|
|
||||||
RTV,
|
|
||||||
DSV
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class QueryType : uint8_t {
|
|
||||||
Occlusion,
|
|
||||||
Timestamp,
|
|
||||||
PipelineStatistics
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SampleCount : uint8_t {
|
|
||||||
Count1 = 1,
|
|
||||||
Count2 = 2,
|
|
||||||
Count4 = 4,
|
|
||||||
Count8 = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommandQueueDesc {
|
|
||||||
CommandListType type = CommandListType::Direct;
|
|
||||||
int32_t priority = 0;
|
|
||||||
const char* name = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DescriptorHeapDesc {
|
|
||||||
DescriptorHeapType type;
|
|
||||||
uint32_t count = 0;
|
|
||||||
bool shaderVisible = false;
|
|
||||||
const char* name = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueryHeapDesc {
|
|
||||||
QueryType type;
|
|
||||||
uint32_t count = 0;
|
|
||||||
const char* name = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SwapChainDesc {
|
|
||||||
uint32_t width = 0;
|
|
||||||
uint32_t height = 0;
|
|
||||||
Format format = Format::Unknown;
|
|
||||||
uint32_t bufferCount = 2;
|
|
||||||
bool vsync = false;
|
|
||||||
bool fullscreen = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ResourceStateFlag : uint32_t {
|
|
||||||
Common = 0,
|
|
||||||
VertexBuffer = 1 << 0,
|
|
||||||
ConstantBuffer = 1 << 1,
|
|
||||||
IndexBuffer = 1 << 2,
|
|
||||||
RenderTarget = 1 << 3,
|
|
||||||
UnorderedAccess = 1 << 4,
|
|
||||||
DepthWrite = 1 << 5,
|
|
||||||
DepthRead = 1 << 6,
|
|
||||||
ShaderResource = 1 << 7,
|
|
||||||
IndirectArgument = 1 << 8,
|
|
||||||
CopyDest = 1 << 9,
|
|
||||||
CopySource = 1 << 10,
|
|
||||||
ResolveDest = 1 << 11,
|
|
||||||
ResolveSource = 1 << 12,
|
|
||||||
Present = 1 << 13,
|
|
||||||
RaytracingAccelerationStructure = 1 << 14,
|
|
||||||
ShadingRateSource = 1 << 15
|
|
||||||
};
|
|
||||||
|
|
||||||
inline ResourceStateFlag operator|(ResourceStateFlag a, ResourceStateFlag b) {
|
|
||||||
return static_cast<ResourceStateFlag>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ResourceStateFlag operator&(ResourceStateFlag a, ResourceStateFlag b) {
|
|
||||||
return static_cast<ResourceStateFlag>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Viewport {
|
|
||||||
float topLeftX = 0.0f;
|
|
||||||
float topLeftY = 0.0f;
|
|
||||||
float width = 0.0f;
|
|
||||||
float height = 0.0f;
|
|
||||||
float minDepth = 0.0f;
|
|
||||||
float maxDepth = 1.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rect {
|
|
||||||
int32_t left = 0;
|
|
||||||
int32_t top = 0;
|
|
||||||
int32_t right = 0;
|
|
||||||
int32_t bottom = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Color {
|
|
||||||
float r = 0.0f;
|
|
||||||
float g = 0.0f;
|
|
||||||
float b = 0.0f;
|
|
||||||
float a = 1.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClearValue {
|
|
||||||
Color color;
|
|
||||||
float depth = 1.0f;
|
|
||||||
uint8_t stencil = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline DXGI_FORMAT FormatToDXGIFormat(Format format) {
|
|
||||||
switch (format) {
|
|
||||||
case Format::Unknown: return DXGI_FORMAT_UNKNOWN;
|
|
||||||
case Format::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
|
||||||
case Format::R8G8_UNorm: return DXGI_FORMAT_R8G8_UNORM;
|
|
||||||
case Format::R8G8B8A8_UNorm: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
case Format::R16G16B16A16_Float: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
|
||||||
case Format::R32G32B32A32_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
||||||
case Format::R16_Float: return DXGI_FORMAT_R16_FLOAT;
|
|
||||||
case Format::R32_Float: return DXGI_FORMAT_R32_FLOAT;
|
|
||||||
case Format::D16_UNorm: return DXGI_FORMAT_D16_UNORM;
|
|
||||||
case Format::D24_UNorm_S8_UInt: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
||||||
case Format::D32_Float: return DXGI_FORMAT_D32_FLOAT;
|
|
||||||
case Format::BC1_UNorm: return DXGI_FORMAT_BC1_UNORM;
|
|
||||||
case Format::BC2_UNorm: return DXGI_FORMAT_BC2_UNORM;
|
|
||||||
case Format::BC3_UNorm: return DXGI_FORMAT_BC3_UNORM;
|
|
||||||
case Format::BC4_UNorm: return DXGI_FORMAT_BC4_UNORM;
|
|
||||||
case Format::BC5_UNorm: return DXGI_FORMAT_BC5_UNORM;
|
|
||||||
case Format::BC6H_UF16: return DXGI_FORMAT_BC6H_UF16;
|
|
||||||
case Format::BC7_UNorm: return DXGI_FORMAT_BC7_UNORM;
|
|
||||||
default: return DXGI_FORMAT_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Format DXGIFormatToFormat(DXGI_FORMAT dxgiFormat) {
|
|
||||||
switch (dxgiFormat) {
|
|
||||||
case DXGI_FORMAT_UNKNOWN: return Format::Unknown;
|
|
||||||
case DXGI_FORMAT_R8_UNORM: return Format::R8_UNorm;
|
|
||||||
case DXGI_FORMAT_R8G8_UNORM: return Format::R8G8_UNorm;
|
|
||||||
case DXGI_FORMAT_R8G8B8A8_UNORM: return Format::R8G8B8A8_UNorm;
|
|
||||||
case DXGI_FORMAT_R16G16B16A16_FLOAT: return Format::R16G16B16A16_Float;
|
|
||||||
case DXGI_FORMAT_R32G32B32A32_FLOAT: return Format::R32G32B32A32_Float;
|
|
||||||
case DXGI_FORMAT_R16_FLOAT: return Format::R16_Float;
|
|
||||||
case DXGI_FORMAT_R32_FLOAT: return Format::R32_Float;
|
|
||||||
case DXGI_FORMAT_D16_UNORM: return Format::D16_UNorm;
|
|
||||||
case DXGI_FORMAT_D24_UNORM_S8_UINT: return Format::D24_UNorm_S8_UInt;
|
|
||||||
case DXGI_FORMAT_D32_FLOAT: return Format::D32_Float;
|
|
||||||
case DXGI_FORMAT_BC1_UNORM: return Format::BC1_UNorm;
|
|
||||||
case DXGI_FORMAT_BC2_UNORM: return Format::BC2_UNorm;
|
|
||||||
case DXGI_FORMAT_BC3_UNORM: return Format::BC3_UNorm;
|
|
||||||
case DXGI_FORMAT_BC4_UNORM: return Format::BC4_UNorm;
|
|
||||||
case DXGI_FORMAT_BC5_UNORM: return Format::BC5_UNorm;
|
|
||||||
case DXGI_FORMAT_BC6H_UF16: return Format::BC6H_UF16;
|
|
||||||
case DXGI_FORMAT_BC7_UNORM: return Format::BC7_UNorm;
|
|
||||||
default: return Format::Unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RHIDefines.h"
|
|
||||||
#include "IRHIDevice.h"
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class RHISystem {
|
|
||||||
public:
|
|
||||||
static RHISystem& Get();
|
|
||||||
|
|
||||||
bool Initialize(GraphicsAPI api, void* windowHandle, uint32_t width, uint32_t height);
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
IRHIDevice* GetDevice() { return m_device; }
|
|
||||||
GraphicsAPI GetAPI() const { return m_api; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
RHISystem() = default;
|
|
||||||
~RHISystem() = default;
|
|
||||||
|
|
||||||
GraphicsAPI m_api = GraphicsAPI::Unknown;
|
|
||||||
IRHIDevice* m_device = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <RHI\IRHIDevice.h>
|
|
||||||
#include <RHI\IRHIResources.h>
|
|
||||||
#include <Rendering\RenderTarget.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class D3D12DescriptorHeap;
|
|
||||||
|
|
||||||
class RenderContext {
|
|
||||||
public:
|
|
||||||
RenderContext(D3D12Device* device);
|
|
||||||
~RenderContext();
|
|
||||||
|
|
||||||
bool Initialize(uint32_t width, uint32_t height);
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void BeginFrame();
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
ICommandList* GetCommandList() { return m_commandList; }
|
|
||||||
ICommandAllocator* GetCommandAllocator() { return m_commandAllocator; }
|
|
||||||
ISwapChain* GetSwapChain() { return m_swapChain; }
|
|
||||||
IRenderTarget* GetCurrentRenderTarget() { return m_currentRenderTarget; }
|
|
||||||
IDepthStencil* GetDepthStencil() { return m_depthStencil; }
|
|
||||||
IFence* GetFence() { return m_fence; }
|
|
||||||
uint64_t GetFenceValue() { return m_fenceValue; }
|
|
||||||
void IncrementFenceValue() { m_fenceValue++; }
|
|
||||||
void WaitForCompletionOfCommandList() { m_fence->Wait(m_fenceValue); }
|
|
||||||
|
|
||||||
void SetViewport(float width, float height);
|
|
||||||
void SetScissor(int32_t width, int32_t height);
|
|
||||||
void ClearRenderTarget(const float color[4]);
|
|
||||||
void ClearDepthStencil();
|
|
||||||
void Present();
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
ICommandAllocator* m_commandAllocator = nullptr;
|
|
||||||
ICommandList* m_commandList = nullptr;
|
|
||||||
IFence* m_fence = nullptr;
|
|
||||||
ISwapChain* m_swapChain = nullptr;
|
|
||||||
IRenderTarget* m_currentRenderTarget = nullptr;
|
|
||||||
IDepthStencil* m_depthStencil = nullptr;
|
|
||||||
D3D12DescriptorHeap* m_dsvHeap = nullptr;
|
|
||||||
uint64_t m_fenceValue = 0;
|
|
||||||
uint32_t m_width = 0;
|
|
||||||
uint32_t m_height = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Rendering/Resources.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class D3D12Device;
|
|
||||||
class D3D12SwapChain;
|
|
||||||
class D3D12DescriptorHeap;
|
|
||||||
|
|
||||||
class IDepthStencil : public ITexture2D {
|
|
||||||
public:
|
|
||||||
virtual ~IDepthStencil() = default;
|
|
||||||
virtual void SetDSVHeap(void* heap) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IRenderTarget : public ITexture2D {
|
|
||||||
public:
|
|
||||||
virtual ~IRenderTarget() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CreateDepthStencil(D3D12Device* device, uint32_t width, uint32_t height, Format format, IDepthStencil** outDepthStencil);
|
|
||||||
|
|
||||||
bool CreateRenderTargetFromSwapChain(D3D12Device* device, D3D12SwapChain* swapChain, uint32_t bufferIndex, IRenderTarget** outRenderTarget);
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <RHI\IRHIDevice.h>
|
|
||||||
#include <RHI\IRHIResources.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
struct BufferDesc {
|
|
||||||
uint64_t size = 0;
|
|
||||||
uint32_t stride = 0;
|
|
||||||
bool cpuAccessible = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IBuffer : public IResource {
|
|
||||||
public:
|
|
||||||
virtual ~IBuffer() = default;
|
|
||||||
virtual const BufferDesc& GetDesc() const = 0;
|
|
||||||
virtual void* Map() = 0;
|
|
||||||
virtual void Unmap() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IVertexBuffer : public IBuffer {
|
|
||||||
public:
|
|
||||||
virtual ~IVertexBuffer() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IIndexBuffer : public IBuffer {
|
|
||||||
public:
|
|
||||||
virtual ~IIndexBuffer() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IConstantBuffer : public IBuffer {
|
|
||||||
public:
|
|
||||||
virtual ~IConstantBuffer() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextureDesc {
|
|
||||||
uint32_t width = 0;
|
|
||||||
uint32_t height = 0;
|
|
||||||
uint32_t depth = 1;
|
|
||||||
uint32_t mipLevels = 1;
|
|
||||||
uint32_t arraySize = 1;
|
|
||||||
Format format = Format::Unknown;
|
|
||||||
bool renderTarget = false;
|
|
||||||
bool depthStencil = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ITexture2D : public IResource {
|
|
||||||
public:
|
|
||||||
virtual ~ITexture2D() = default;
|
|
||||||
virtual const TextureDesc& GetDesc() const = 0;
|
|
||||||
virtual void CreateSRV() = 0;
|
|
||||||
virtual void* GetSRV() = 0;
|
|
||||||
virtual void CreateRTV() = 0;
|
|
||||||
virtual void* GetRTV() = 0;
|
|
||||||
virtual void CreateDSV() = 0;
|
|
||||||
virtual void* GetDSV() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ITextureCube : public IResource {
|
|
||||||
public:
|
|
||||||
virtual ~ITextureCube() = default;
|
|
||||||
virtual const TextureDesc& GetDesc() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISampler {
|
|
||||||
public:
|
|
||||||
virtual ~ISampler() = default;
|
|
||||||
virtual void* GetNativeSampler() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <RHI\RHIDefines.h>
|
|
||||||
#include <RHI\IRHIDevice.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class IShader {
|
|
||||||
public:
|
|
||||||
virtual ~IShader() = default;
|
|
||||||
virtual const ShaderBytecode& GetBytecode() const = 0;
|
|
||||||
virtual const char* GetEntryPoint() const = 0;
|
|
||||||
virtual const char* GetTarget() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CompileShader(const char* filePath, const char* entryPoint, const char* target, ShaderBytecode& outBytecode);
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <Rendering\Resources.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
struct MeshVertex {
|
|
||||||
float position[4];
|
|
||||||
float texcoord[4];
|
|
||||||
float normal[4];
|
|
||||||
float tangent[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SubMesh {
|
|
||||||
IIndexBuffer* indexBuffer = nullptr;
|
|
||||||
uint32_t indexCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StaticMeshComponent {
|
|
||||||
public:
|
|
||||||
StaticMeshComponent();
|
|
||||||
~StaticMeshComponent();
|
|
||||||
|
|
||||||
bool Initialize(ICommandList* commandList, const char* filePath);
|
|
||||||
void Render(ICommandList* commandList);
|
|
||||||
|
|
||||||
IVertexBuffer* GetVertexBuffer() { return m_vertexBuffer; }
|
|
||||||
uint32_t GetVertexCount() const { return m_vertexCount; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
IVertexBuffer* m_vertexBuffer = nullptr;
|
|
||||||
uint32_t m_vertexCount = 0;
|
|
||||||
std::unordered_map<std::string, SubMesh*> m_subMeshes;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
|
||||||
|
|
||||||
set(D3D12_SOURCES
|
|
||||||
D3D12Device.cpp
|
|
||||||
D3D12Resources.cpp
|
|
||||||
D3D12RenderTarget.cpp
|
|
||||||
D3D12Shader.cpp
|
|
||||||
D3D12RenderContext.cpp
|
|
||||||
D3D12StaticMeshComponent.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(XCEngineD3D12 STATIC ${D3D12_SOURCES})
|
|
||||||
|
|
||||||
target_include_directories(XCEngineD3D12 PUBLIC
|
|
||||||
${CMAKE_SOURCE_DIR}/engine/include
|
|
||||||
${CMAKE_SOURCE_DIR}/engine/include/XCEngine
|
|
||||||
${CMAKE_SOURCE_DIR}/engine/src
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(XCEngineD3D12 PUBLIC
|
|
||||||
dxguid
|
|
||||||
d3d12
|
|
||||||
d3dcompiler
|
|
||||||
)
|
|
||||||
@@ -1,892 +0,0 @@
|
|||||||
#include "D3D12RHI.h"
|
|
||||||
#include "D3D12Resources.h"
|
|
||||||
#include <RHI\RHIDefines.h>
|
|
||||||
#include <Rendering\Resources.h>
|
|
||||||
#include <string>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
void EngineLog(const char* msg, ...) {
|
|
||||||
char buffer[1024];
|
|
||||||
va_list args;
|
|
||||||
va_start(args, msg);
|
|
||||||
vsnprintf(buffer, sizeof(buffer), msg, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
FILE* f = nullptr;
|
|
||||||
fopen_s(&f, "D:\\xcengine_debug.log", "a");
|
|
||||||
if (f) { fprintf(f, "%s\n", buffer); fclose(f); }
|
|
||||||
|
|
||||||
printf("%s\n", buffer);
|
|
||||||
OutputDebugStringA(buffer);
|
|
||||||
OutputDebugStringA("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
D3D12Device::D3D12Device() {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Device::~D3D12Device() {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateDXGIDevice(void* windowHandle) {
|
|
||||||
|
|
||||||
UINT dxgiFactoryFlags = 0;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
ID3D12Debug* debugController = nullptr;
|
|
||||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
|
||||||
debugController->EnableDebugLayer();
|
|
||||||
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HRESULT hr = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&m_dxgiFactory));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter;
|
|
||||||
int adapterIndex = 0;
|
|
||||||
bool adapterFound = false;
|
|
||||||
|
|
||||||
while (m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
|
||||||
DXGI_ADAPTER_DESC1 desc;
|
|
||||||
adapter->GetDesc1(&desc);
|
|
||||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
|
||||||
adapterIndex++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
adapterFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
adapterIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adapterFound) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_adapter = adapter;
|
|
||||||
|
|
||||||
hr = D3D12CreateDevice(m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::Initialize(void* windowHandle, uint32_t width, uint32_t height) {
|
|
||||||
if (!CreateDXGIDevice(windowHandle)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
||||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
||||||
queueDesc.Priority = 0;
|
|
||||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
|
|
||||||
HRESULT hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_commandQueue = new D3D12CommandQueue(this, commandQueue.Get());
|
|
||||||
|
|
||||||
SwapChainDesc swapChainDesc = {};
|
|
||||||
swapChainDesc.width = width;
|
|
||||||
swapChainDesc.height = height;
|
|
||||||
swapChainDesc.format = Format::R8G8B8A8_UNorm;
|
|
||||||
swapChainDesc.bufferCount = 2;
|
|
||||||
swapChainDesc.vsync = false;
|
|
||||||
swapChainDesc.fullscreen = false;
|
|
||||||
|
|
||||||
ISwapChain* swapChain = nullptr;
|
|
||||||
if (!CreateSwapChain(&swapChain, swapChainDesc, windowHandle)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_swapChain = static_cast<D3D12SwapChain*>(swapChain);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Device::Shutdown() {
|
|
||||||
if (m_commandQueue) {
|
|
||||||
delete m_commandQueue;
|
|
||||||
m_commandQueue = nullptr;
|
|
||||||
}
|
|
||||||
if (m_swapChain) {
|
|
||||||
delete m_swapChain;
|
|
||||||
m_swapChain = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) {
|
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
||||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
||||||
queueDesc.Priority = desc.priority;
|
|
||||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
|
|
||||||
HRESULT hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*queue = new D3D12CommandQueue(this, commandQueue.Get());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateCommandAllocator(ICommandAllocator** allocator) {
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocator;
|
|
||||||
HRESULT hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*allocator = new D3D12CommandAllocator(this, commandAllocator.Get());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateCommandList(ICommandList** list, ICommandAllocator* allocator) {
|
|
||||||
D3D12CommandAllocator* d3d12Allocator = static_cast<D3D12CommandAllocator*>(allocator);
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList;
|
|
||||||
HRESULT hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
|
||||||
d3d12Allocator->GetNativeAllocator(), nullptr, IID_PPV_ARGS(&commandList));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*list = new D3D12CommandList(this, commandList.Get());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateFence(IFence** fence) {
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Fence> d3dFence;
|
|
||||||
HRESULT hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3dFence));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*fence = new D3D12Fence(this, d3dFence.Get());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) {
|
|
||||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
|
|
||||||
heapDesc.NumDescriptors = desc.count;
|
|
||||||
heapDesc.Flags = desc.shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
|
||||||
|
|
||||||
switch (desc.type) {
|
|
||||||
case DescriptorHeapType::CBV_SRV_UAV:
|
|
||||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
||||||
break;
|
|
||||||
case DescriptorHeapType::Sampler:
|
|
||||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
|
||||||
break;
|
|
||||||
case DescriptorHeapType::RTV:
|
|
||||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
|
||||||
break;
|
|
||||||
case DescriptorHeapType::DSV:
|
|
||||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> descriptorHeap;
|
|
||||||
HRESULT hr = m_device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&descriptorHeap));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*heap = new D3D12DescriptorHeap(this, descriptorHeap.Get(), desc.type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateRootSignature(IRootSignature** signature, const RootSignatureDesc& desc) {
|
|
||||||
*signature = new D3D12RootSignature(this);
|
|
||||||
return (*signature)->Initialize(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreatePipelineState(IPipelineState** pso, const PipelineDesc& desc) {
|
|
||||||
*pso = new D3D12PipelineState(this);
|
|
||||||
return static_cast<D3D12PipelineState*>(*pso)->Initialize(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12Device::CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) {
|
|
||||||
*swapChain = new D3D12SwapChain(this);
|
|
||||||
bool result = (*swapChain)->Initialize(desc, windowHandle);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandQueue::D3D12CommandQueue(D3D12Device* device, ID3D12CommandQueue* queue)
|
|
||||||
: m_device(device), m_commandQueue(queue) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandQueue::~D3D12CommandQueue() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandQueue::ExecuteCommandLists(void** lists, uint32_t count) {
|
|
||||||
ID3D12CommandList** d3dLists = reinterpret_cast<ID3D12CommandList**>(lists);
|
|
||||||
m_commandQueue->ExecuteCommandLists(count, d3dLists);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandQueue::Signal(void* fence, uint64_t value) {
|
|
||||||
ID3D12Fence* d3dFence = static_cast<ID3D12Fence*>(fence);
|
|
||||||
m_commandQueue->Signal(d3dFence, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandQueue::Wait(void* fence, uint64_t value) {
|
|
||||||
ID3D12Fence* d3dFence = static_cast<ID3D12Fence*>(fence);
|
|
||||||
m_commandQueue->Wait(d3dFence, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t D3D12CommandQueue::GetTimestampFrequency() const {
|
|
||||||
uint64_t frequency = 0;
|
|
||||||
m_commandQueue->GetTimestampFrequency(&frequency);
|
|
||||||
return frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandAllocator::D3D12CommandAllocator(D3D12Device* device, ID3D12CommandAllocator* allocator)
|
|
||||||
: m_device(device), m_commandAllocator(allocator) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandAllocator::~D3D12CommandAllocator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandAllocator::Reset() {
|
|
||||||
m_commandAllocator->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Fence::D3D12Fence(D3D12Device* device, ID3D12Fence* fence)
|
|
||||||
: m_device(device), m_fence(fence) {
|
|
||||||
m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Fence::~D3D12Fence() {
|
|
||||||
if (m_fenceEvent) {
|
|
||||||
CloseHandle(m_fenceEvent);
|
|
||||||
m_fenceEvent = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t D3D12Fence::GetCompletedValue() const {
|
|
||||||
return m_fence->GetCompletedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Fence::Signal(uint64_t value) {
|
|
||||||
m_fence->Signal(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Fence::Wait(uint64_t value) {
|
|
||||||
if (m_fence->GetCompletedValue() < value) {
|
|
||||||
m_fence->SetEventOnCompletion(value, m_fenceEvent);
|
|
||||||
WaitForSingleObject(m_fenceEvent, INFINITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Fence::Wait(uint64_t value, uint64_t timeoutMs) {
|
|
||||||
if (m_fence->GetCompletedValue() < value) {
|
|
||||||
m_fence->SetEventOnCompletion(value, m_fenceEvent);
|
|
||||||
WaitForSingleObject(m_fenceEvent, (DWORD)timeoutMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12DescriptorHeap::D3D12DescriptorHeap(D3D12Device* device, ID3D12DescriptorHeap* heap, DescriptorHeapType type)
|
|
||||||
: m_device(device), m_descriptorHeap(heap), m_type(type) {
|
|
||||||
m_descriptorCount = heap->GetDesc().NumDescriptors;
|
|
||||||
m_descriptorSize = device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
|
|
||||||
type == DescriptorHeapType::CBV_SRV_UAV ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV :
|
|
||||||
type == DescriptorHeapType::Sampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER :
|
|
||||||
type == DescriptorHeapType::RTV ? D3D12_DESCRIPTOR_HEAP_TYPE_RTV : D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12DescriptorHeap::~D3D12DescriptorHeap() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12DescriptorHeap::GetCPUDescriptorHandle(uint32_t index) const {
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
|
||||||
handle.ptr += index * m_descriptorSize;
|
|
||||||
return (void*)handle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t D3D12DescriptorHeap::GetGPUDescriptorHandle(uint32_t index) const {
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
|
||||||
handle.ptr += index * m_descriptorSize;
|
|
||||||
return handle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12DescriptorHeap::SetName(const char* name) {
|
|
||||||
if (name) {
|
|
||||||
m_descriptorHeap->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12SwapChain::D3D12SwapChain(D3D12Device* device)
|
|
||||||
: m_device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12SwapChain::~D3D12SwapChain() {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12SwapChain::Initialize(const SwapChainDesc& desc, void* windowHandle) {
|
|
||||||
m_bufferCount = desc.bufferCount;
|
|
||||||
m_vsync = desc.vsync;
|
|
||||||
m_fullscreen = desc.fullscreen;
|
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
|
||||||
swapChainDesc.BufferCount = desc.bufferCount;
|
|
||||||
swapChainDesc.BufferDesc.Width = desc.width;
|
|
||||||
swapChainDesc.BufferDesc.Height = desc.height;
|
|
||||||
swapChainDesc.BufferDesc.Format = FormatToDXGIFormat(desc.format);
|
|
||||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
||||||
swapChainDesc.OutputWindow = (HWND)windowHandle;
|
|
||||||
swapChainDesc.SampleDesc.Count = 1;
|
|
||||||
swapChainDesc.Windowed = !desc.fullscreen;
|
|
||||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
|
|
||||||
ID3D12CommandQueue* cmdQueue = (ID3D12CommandQueue*)m_device->GetCommandQueue()->GetNativeQueue();
|
|
||||||
HRESULT hr = m_device->GetDXGIFactory()->CreateSwapChain(
|
|
||||||
cmdQueue, &swapChainDesc, &swapChain);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = swapChain.As(&m_swapChain);
|
|
||||||
|
|
||||||
DescriptorHeapDesc rtvDesc = {};
|
|
||||||
rtvDesc.type = DescriptorHeapType::RTV;
|
|
||||||
rtvDesc.count = desc.bufferCount;
|
|
||||||
rtvDesc.shaderVisible = false;
|
|
||||||
|
|
||||||
if (!m_device->CreateDescriptorHeap((IDescriptorHeap**)&m_rtvHeap, rtvDesc)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHeapStart;
|
|
||||||
rtvHeapStart.ptr = (UINT64)m_rtvHeap->GetCPUDescriptorHandle(0);
|
|
||||||
|
|
||||||
UINT rtvDescriptorSize = m_device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < desc.bufferCount; i++) {
|
|
||||||
hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i]));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvPointer;
|
|
||||||
rtvPointer.ptr = rtvHeapStart.ptr + i * rtvDescriptorSize;
|
|
||||||
m_device->GetD3D12Device()->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtvPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12SwapChain::Shutdown() {
|
|
||||||
m_buffers[0].Reset();
|
|
||||||
if (m_rtvHeap) {
|
|
||||||
delete m_rtvHeap;
|
|
||||||
m_rtvHeap = nullptr;
|
|
||||||
}
|
|
||||||
m_swapChain.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12SwapChain::Present() {
|
|
||||||
HRESULT hr = m_swapChain->Present(m_vsync ? 1 : 0, 0);
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12SwapChain::Resize(uint32_t width, uint32_t height) {
|
|
||||||
for (uint32_t i = 0; i < m_bufferCount; i++) {
|
|
||||||
m_buffers[i].Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT hr = m_swapChain->ResizeBuffers(m_bufferCount, width, height, DXGI_FORMAT_UNKNOWN, 0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = *(D3D12_CPU_DESCRIPTOR_HANDLE*)m_rtvHeap->GetCPUDescriptorHandle(0);
|
|
||||||
for (uint32_t i = 0; i < m_bufferCount; i++) {
|
|
||||||
hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i]));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_device->GetD3D12Device()->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtvHandle);
|
|
||||||
rtvHandle.ptr += m_rtvHeap->GetDescriptorSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t D3D12SwapChain::GetCurrentBufferIndex() const {
|
|
||||||
return m_swapChain->GetCurrentBackBufferIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12SwapChain::GetBuffer(uint32_t index) {
|
|
||||||
return GetBufferResource(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12SwapChain::GetCurrentRenderTarget() {
|
|
||||||
uint32_t index = GetCurrentBufferIndex();
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_rtvHeap->GetNativeHeap()->GetCPUDescriptorHandleForHeapStart();
|
|
||||||
UINT rtvSize = m_device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
|
||||||
handle.ptr += index * rtvSize;
|
|
||||||
return (void*)handle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12SwapChain::GetDepthStencil() {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12SwapChain::SetFullscreen(bool fullscreen) {
|
|
||||||
m_fullscreen = fullscreen;
|
|
||||||
m_swapChain->SetFullscreenState(fullscreen, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12SwapChain::IsFullscreen() const {
|
|
||||||
return m_fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12RootSignature::D3D12RootSignature(D3D12Device* device)
|
|
||||||
: m_device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12RootSignature::~D3D12RootSignature() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12RootSignature::Initialize(const RootSignatureDesc& desc) {
|
|
||||||
EngineLog("RootSignature: Start init, paramCount=%u", desc.parameterCount);
|
|
||||||
D3D12_ROOT_PARAMETER rootParameters[16] = {};
|
|
||||||
D3D12_DESCRIPTOR_RANGE descriptorRanges[16] = {};
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < desc.parameterCount && i < 16; i++) {
|
|
||||||
const RootParameter& param = desc.parameters[i];
|
|
||||||
|
|
||||||
switch (param.type) {
|
|
||||||
case RootParameterType::CBV:
|
|
||||||
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
||||||
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
||||||
rootParameters[i].Descriptor.RegisterSpace = param.registerSpace;
|
|
||||||
rootParameters[i].Descriptor.ShaderRegister = param.shaderRegister;
|
|
||||||
break;
|
|
||||||
case RootParameterType::SRV:
|
|
||||||
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
||||||
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
||||||
rootParameters[i].Descriptor.RegisterSpace = param.registerSpace;
|
|
||||||
rootParameters[i].Descriptor.ShaderRegister = param.shaderRegister;
|
|
||||||
break;
|
|
||||||
case RootParameterType::Constants:
|
|
||||||
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
|
||||||
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
||||||
rootParameters[i].Constants.RegisterSpace = param.registerSpace;
|
|
||||||
rootParameters[i].Constants.ShaderRegister = param.shaderRegister;
|
|
||||||
rootParameters[i].Constants.Num32BitValues = param.num32BitValues;
|
|
||||||
break;
|
|
||||||
case RootParameterType::DescriptorTable:
|
|
||||||
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
||||||
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
||||||
rootParameters[i].DescriptorTable.pDescriptorRanges = &descriptorRanges[i];
|
|
||||||
rootParameters[i].DescriptorTable.NumDescriptorRanges = 1;
|
|
||||||
|
|
||||||
descriptorRanges[i].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
||||||
descriptorRanges[i].RegisterSpace = param.registerSpace;
|
|
||||||
descriptorRanges[i].BaseShaderRegister = 0;
|
|
||||||
descriptorRanges[i].NumDescriptors = 1;
|
|
||||||
descriptorRanges[i].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rootParameters[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
EngineLog("RootParam[%d]: type=%d, visibility=%d, reg=%d, space=%d",
|
|
||||||
i, (int)param.type, (int)param.visibility, param.shaderRegister, param.registerSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_STATIC_SAMPLER_DESC samplerDesc = {};
|
|
||||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
samplerDesc.RegisterSpace = 0;
|
|
||||||
samplerDesc.ShaderRegister = 0;
|
|
||||||
samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
|
||||||
|
|
||||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
|
||||||
rootSignatureDesc.NumParameters = desc.parameterCount;
|
|
||||||
rootSignatureDesc.pParameters = rootParameters;
|
|
||||||
rootSignatureDesc.NumStaticSamplers = 1;
|
|
||||||
rootSignatureDesc.pStaticSamplers = &samplerDesc;
|
|
||||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3DBlob> signature;
|
|
||||||
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
|
|
||||||
HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &errorBlob);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
if (errorBlob) {
|
|
||||||
OutputDebugStringA((const char*)errorBlob->GetBufferPointer());
|
|
||||||
}
|
|
||||||
EngineLog("RootSignature: Serialize FAILED");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EngineLog("RootSignature: Serialize SUCCESS, size=%llu", (unsigned long long)signature->GetBufferSize());
|
|
||||||
|
|
||||||
hr = m_device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(),
|
|
||||||
IID_PPV_ARGS(&m_rootSignature));
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
EngineLog("RootSignature: SUCCESS");
|
|
||||||
} else {
|
|
||||||
EngineLog("RootSignature: FAILED");
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12RootSignature::SetName(const char* name) {
|
|
||||||
if (name && m_rootSignature) {
|
|
||||||
m_rootSignature->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12RootSignature::GetNativeRootSignature() const {
|
|
||||||
return m_rootSignature.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12PipelineState::D3D12PipelineState(D3D12Device* device)
|
|
||||||
: m_device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12PipelineState::~D3D12PipelineState() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool D3D12PipelineState::Initialize(const PipelineDesc& desc) {
|
|
||||||
EngineLog("PipelineState: Start init");
|
|
||||||
|
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
||||||
|
|
||||||
if (desc.rootSignature) {
|
|
||||||
EngineLog("PipelineState: has rootSignature");
|
|
||||||
D3D12RootSignature* rs = static_cast<D3D12RootSignature*>(desc.rootSignature);
|
|
||||||
psoDesc.pRootSignature = rs->GetNative();
|
|
||||||
EngineLog("PipelineState: rootSignature ptr=%p", psoDesc.pRootSignature);
|
|
||||||
} else {
|
|
||||||
EngineLog("PipelineState: NO rootSignature!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc.vertexShader.size > 0 && desc.vertexShader.bytecode != nullptr) {
|
|
||||||
psoDesc.VS.pShaderBytecode = desc.vertexShader.bytecode;
|
|
||||||
psoDesc.VS.BytecodeLength = desc.vertexShader.size;
|
|
||||||
}
|
|
||||||
if (desc.pixelShader.size > 0 && desc.pixelShader.bytecode != nullptr) {
|
|
||||||
psoDesc.PS.pShaderBytecode = desc.pixelShader.bytecode;
|
|
||||||
psoDesc.PS.BytecodeLength = desc.pixelShader.size;
|
|
||||||
}
|
|
||||||
if (desc.geometryShader.size > 0 && desc.geometryShader.bytecode != nullptr) {
|
|
||||||
psoDesc.GS.pShaderBytecode = desc.geometryShader.bytecode;
|
|
||||||
psoDesc.GS.BytecodeLength = desc.geometryShader.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_INPUT_ELEMENT_DESC d3d12Elements[16] = {};
|
|
||||||
for (uint32_t i = 0; i < desc.inputLayout.elementCount && i < 16; i++) {
|
|
||||||
const InputElementDesc& src = desc.inputLayout.elements[i];
|
|
||||||
d3d12Elements[i].SemanticName = src.semanticName;
|
|
||||||
d3d12Elements[i].SemanticIndex = src.semanticIndex;
|
|
||||||
d3d12Elements[i].Format = FormatToDXGIFormat(src.format);
|
|
||||||
d3d12Elements[i].InputSlot = src.inputSlot;
|
|
||||||
d3d12Elements[i].AlignedByteOffset = src.alignedByteOffset;
|
|
||||||
d3d12Elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
|
||||||
d3d12Elements[i].InstanceDataStepRate = 0;
|
|
||||||
}
|
|
||||||
psoDesc.InputLayout.NumElements = desc.inputLayout.elementCount;
|
|
||||||
psoDesc.InputLayout.pInputElementDescs = d3d12Elements;
|
|
||||||
|
|
||||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
|
||||||
psoDesc.NumRenderTargets = 1;
|
|
||||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
||||||
psoDesc.SampleDesc.Count = 1;
|
|
||||||
psoDesc.SampleDesc.Quality = 0;
|
|
||||||
psoDesc.SampleMask = 0xffffffff;
|
|
||||||
|
|
||||||
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
|
||||||
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
|
||||||
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
|
||||||
|
|
||||||
psoDesc.DepthStencilState.DepthEnable = TRUE;
|
|
||||||
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
|
||||||
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
|
||||||
|
|
||||||
psoDesc.BlendState = { 0 };
|
|
||||||
D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc = {
|
|
||||||
FALSE,FALSE,
|
|
||||||
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
|
||||||
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
|
||||||
D3D12_LOGIC_OP_NOOP,
|
|
||||||
D3D12_COLOR_WRITE_ENABLE_ALL,
|
|
||||||
};
|
|
||||||
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
|
||||||
psoDesc.BlendState.RenderTarget[i] = rtBlendDesc;
|
|
||||||
|
|
||||||
EngineLog("PSO: VS=%p(%u), PS=%p(%u), RTV=%d, DSV=%d",
|
|
||||||
psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength,
|
|
||||||
psoDesc.PS.pShaderBytecode, psoDesc.PS.BytecodeLength,
|
|
||||||
psoDesc.RTVFormats[0], psoDesc.DSVFormat);
|
|
||||||
|
|
||||||
HRESULT hr = m_device->GetD3D12Device()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
EngineLog("PipelineState: FAILED with HRESULT=%08lx", (unsigned long)hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
EngineLog("PipelineState: SUCCESS");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12PipelineState::SetName(const char* name) {
|
|
||||||
if (name && m_pipelineState) {
|
|
||||||
m_pipelineState->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12PipelineState::GetNativePipelineState() const {
|
|
||||||
return m_pipelineState.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandList::D3D12CommandList(D3D12Device* device, ID3D12GraphicsCommandList* list)
|
|
||||||
: m_device(device), m_commandList(list) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12CommandList::~D3D12CommandList() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::Reset(void* allocator) {
|
|
||||||
ICommandAllocator* cmdAlloc = static_cast<ICommandAllocator*>(allocator);
|
|
||||||
D3D12CommandAllocator* d3d12Alloc = static_cast<D3D12CommandAllocator*>(cmdAlloc);
|
|
||||||
ID3D12CommandAllocator* d3dAllocator = d3d12Alloc->GetNativeAllocator();
|
|
||||||
m_commandList->Reset(d3dAllocator, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::Close() {
|
|
||||||
m_commandList->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetPipelineState(IPipelineState* pso) {
|
|
||||||
if (pso) {
|
|
||||||
D3D12PipelineState* d3dPso = static_cast<D3D12PipelineState*>(pso);
|
|
||||||
m_commandList->SetPipelineState(d3dPso->GetNative());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetRootSignature(IRootSignature* signature) {
|
|
||||||
if (signature) {
|
|
||||||
D3D12RootSignature* d3dRs = static_cast<D3D12RootSignature*>(signature);
|
|
||||||
m_commandList->SetGraphicsRootSignature(d3dRs->GetNative());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetPrimitiveTopology(PrimitiveTopology topology) {
|
|
||||||
D3D12_PRIMITIVE_TOPOLOGY d3dTopology;
|
|
||||||
switch (topology) {
|
|
||||||
case PrimitiveTopology::TriangleList:
|
|
||||||
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
|
||||||
break;
|
|
||||||
case PrimitiveTopology::TriangleStrip:
|
|
||||||
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
|
||||||
break;
|
|
||||||
case PrimitiveTopology::LineList:
|
|
||||||
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_commandList->IASetPrimitiveTopology(d3dTopology);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetVertexBuffer(uint32_t slot, IResource* buffer, uint32_t offset, uint32_t stride) {
|
|
||||||
if (buffer) {
|
|
||||||
D3D12VertexBuffer* vb = static_cast<D3D12VertexBuffer*>(buffer);
|
|
||||||
D3D12_VERTEX_BUFFER_VIEW vbView = {};
|
|
||||||
vbView.BufferLocation = vb->GetNative()->GetGPUVirtualAddress() + offset;
|
|
||||||
vbView.SizeInBytes = (UINT)vb->GetDesc().size;
|
|
||||||
vbView.StrideInBytes = stride;
|
|
||||||
m_commandList->IASetVertexBuffers(slot, 1, &vbView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetIndexBuffer(IResource* buffer, uint32_t offset) {
|
|
||||||
if (buffer) {
|
|
||||||
D3D12IndexBuffer* ib = static_cast<D3D12IndexBuffer*>(buffer);
|
|
||||||
D3D12_INDEX_BUFFER_VIEW ibView = {};
|
|
||||||
ibView.BufferLocation = ib->GetNative()->GetGPUVirtualAddress() + offset;
|
|
||||||
ibView.Format = DXGI_FORMAT_R32_UINT;
|
|
||||||
ibView.SizeInBytes = (UINT)ib->GetDesc().size;
|
|
||||||
m_commandList->IASetIndexBuffer(&ibView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetDescriptorHeap(IDescriptorHeap* heap) {
|
|
||||||
if (heap) {
|
|
||||||
D3D12DescriptorHeap* d3dHeap = static_cast<D3D12DescriptorHeap*>(heap);
|
|
||||||
ID3D12DescriptorHeap* heaps[] = { d3dHeap->GetNativeHeap() };
|
|
||||||
m_commandList->SetDescriptorHeaps(1, heaps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) {
|
|
||||||
m_commandList->SetGraphicsRootDescriptorTable(rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE{ baseDescriptor });
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetGraphicsRootConstantBufferView(uint32_t slot, IResource* buffer) {
|
|
||||||
if (buffer) {
|
|
||||||
D3D12Resource* d3dBuffer = static_cast<D3D12Resource*>(buffer);
|
|
||||||
m_commandList->SetGraphicsRootConstantBufferView(slot, d3dBuffer->GetNative()->GetGPUVirtualAddress());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetGraphicsRootConstantBufferViewCBV(uint32_t slot, void* nativeResource) {
|
|
||||||
ID3D12Resource* resource = static_cast<ID3D12Resource*>(nativeResource);
|
|
||||||
m_commandList->SetGraphicsRootConstantBufferView(slot, resource->GetGPUVirtualAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetGraphicsRoot32BitConstants(uint32_t rootParameterIndex, uint32_t num32BitValues, const void* data, uint32_t destOffsetIn32BitValues) {
|
|
||||||
m_commandList->SetGraphicsRoot32BitConstants(rootParameterIndex, num32BitValues, data, destOffsetIn32BitValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) {
|
|
||||||
m_commandList->SetComputeRootDescriptorTable(rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE{ baseDescriptor });
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) {
|
|
||||||
m_commandList->DrawInstanced(vertexCountPerInstance, instanceCount, startVertex, startInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) {
|
|
||||||
m_commandList->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndex, baseVertex, startInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::Dispatch(uint32_t x, uint32_t y, uint32_t z) {
|
|
||||||
m_commandList->Dispatch(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetViewports(const Viewport* viewports, uint32_t count) {
|
|
||||||
D3D12_VIEWPORT d3dViewports[16] = {};
|
|
||||||
for (uint32_t i = 0; i < count && i < 16; i++) {
|
|
||||||
d3dViewports[i].TopLeftX = viewports[i].topLeftX;
|
|
||||||
d3dViewports[i].TopLeftY = viewports[i].topLeftY;
|
|
||||||
d3dViewports[i].Width = viewports[i].width;
|
|
||||||
d3dViewports[i].Height = viewports[i].height;
|
|
||||||
d3dViewports[i].MinDepth = viewports[i].minDepth;
|
|
||||||
d3dViewports[i].MaxDepth = viewports[i].maxDepth;
|
|
||||||
}
|
|
||||||
m_commandList->RSSetViewports(count, d3dViewports);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetScissorRects(const Rect* rects, uint32_t count) {
|
|
||||||
D3D12_RECT d3dRects[16] = {};
|
|
||||||
for (uint32_t i = 0; i < count && i < 16; i++) {
|
|
||||||
d3dRects[i].left = rects[i].left;
|
|
||||||
d3dRects[i].top = rects[i].top;
|
|
||||||
d3dRects[i].right = rects[i].right;
|
|
||||||
d3dRects[i].bottom = rects[i].bottom;
|
|
||||||
}
|
|
||||||
m_commandList->RSSetScissorRects(count, d3dRects);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::SetRenderTargets(void** targets, uint32_t count, void* depthStencil) {
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandles[8] = {};
|
|
||||||
for (uint32_t i = 0; i < count && i < 8; i++) {
|
|
||||||
rtvHandles[i].ptr = (UINT64)targets[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = {};
|
|
||||||
if (depthStencil) {
|
|
||||||
dsvHandle.ptr = (UINT64)depthStencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_commandList->OMSetRenderTargets(count, rtvHandles, FALSE, depthStencil ? &dsvHandle : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::ClearRenderTargetView(void* target, const float color[4]) {
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { (UINT64)target };
|
|
||||||
m_commandList->ClearRenderTargetView(rtvHandle, color, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::ClearDepthStencilView(void* depth, float depthValue, uint8_t stencil) {
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = { (UINT64)depth };
|
|
||||||
m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, depthValue, stencil, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::CopyResource(IResource* dst, const IResource* src) {
|
|
||||||
D3D12Resource* d3dDst = static_cast<D3D12Resource*>(dst);
|
|
||||||
D3D12Resource* d3dSrc = static_cast<D3D12Resource*>(const_cast<IResource*>(src));
|
|
||||||
m_commandList->CopyResource(d3dDst->GetNative(), d3dSrc->GetNative());
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) {
|
|
||||||
D3D12Resource* d3dDst = static_cast<D3D12Resource*>(dst);
|
|
||||||
D3D12Resource* d3dSrc = static_cast<D3D12Resource*>(const_cast<IResource*>(src));
|
|
||||||
m_commandList->CopyBufferRegion(d3dDst->GetNative(), dstOffset, d3dSrc->GetNative(), srcOffset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12CommandList::ResourceBarrier(IResource* resource, ResourceStateFlag before, ResourceStateFlag after) {
|
|
||||||
D3D12Resource* d3dResource = static_cast<D3D12Resource*>(resource);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_COMMON;
|
|
||||||
D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_COMMON;
|
|
||||||
|
|
||||||
if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::RenderTarget)) beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::DepthWrite)) beforeState = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::DepthRead)) beforeState = D3D12_RESOURCE_STATE_DEPTH_READ;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::ShaderResource)) beforeState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::CopyDest)) beforeState = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::CopySource)) beforeState = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
||||||
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::Present)) beforeState = D3D12_RESOURCE_STATE_PRESENT;
|
|
||||||
|
|
||||||
if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::RenderTarget)) afterState = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::DepthWrite)) afterState = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::DepthRead)) afterState = D3D12_RESOURCE_STATE_DEPTH_READ;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::ShaderResource)) afterState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::CopyDest)) afterState = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::CopySource)) afterState = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
||||||
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::Present)) afterState = D3D12_RESOURCE_STATE_PRESENT;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
|
||||||
barrier.Transition.pResource = d3dResource->GetNative();
|
|
||||||
barrier.Transition.StateBefore = beforeState;
|
|
||||||
barrier.Transition.StateAfter = afterState;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
|
|
||||||
m_commandList->ResourceBarrier(1, &barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12CommandList::GetNativeCommandList() const {
|
|
||||||
return m_commandList.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Resource::D3D12Resource(D3D12Device* device, ID3D12Resource* resource)
|
|
||||||
: m_device(device), m_resource(resource) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Resource::~D3D12Resource() {
|
|
||||||
m_resource.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <RHI\IRHIDevice.h>
|
|
||||||
#include <RHI\IRHIResources.h>
|
|
||||||
#include <d3d12.h>
|
|
||||||
#include <dxgi1_4.h>
|
|
||||||
#include <wrl\client.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class D3D12Device;
|
|
||||||
|
|
||||||
class D3D12CommandQueue : public ICommandQueue {
|
|
||||||
public:
|
|
||||||
D3D12CommandQueue(D3D12Device* device, ID3D12CommandQueue* queue);
|
|
||||||
~D3D12CommandQueue() override;
|
|
||||||
|
|
||||||
void ExecuteCommandLists(void** lists, uint32_t count) override;
|
|
||||||
void Signal(void* fence, uint64_t value) override;
|
|
||||||
void Wait(void* fence, uint64_t value) override;
|
|
||||||
uint64_t GetTimestampFrequency() const override;
|
|
||||||
|
|
||||||
ID3D12CommandQueue* GetNativeQueue() const { return m_commandQueue.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12CommandAllocator : public ICommandAllocator {
|
|
||||||
public:
|
|
||||||
D3D12CommandAllocator(D3D12Device* device, ID3D12CommandAllocator* allocator);
|
|
||||||
~D3D12CommandAllocator() override;
|
|
||||||
|
|
||||||
void Reset() override;
|
|
||||||
|
|
||||||
ID3D12CommandAllocator* GetNativeAllocator() const { return m_commandAllocator.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocator;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12Fence : public IFence {
|
|
||||||
public:
|
|
||||||
D3D12Fence(D3D12Device* device, ID3D12Fence* fence);
|
|
||||||
~D3D12Fence() override;
|
|
||||||
|
|
||||||
uint64_t GetCompletedValue() const override;
|
|
||||||
void Signal(uint64_t value) override;
|
|
||||||
void Wait(uint64_t value) override;
|
|
||||||
void Wait(uint64_t value, uint64_t timeoutMs) override;
|
|
||||||
|
|
||||||
ID3D12Fence* GetNativeFence() const { return m_fence.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Fence> m_fence;
|
|
||||||
HANDLE m_fenceEvent = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12DescriptorHeap : public IDescriptorHeap {
|
|
||||||
public:
|
|
||||||
D3D12DescriptorHeap(D3D12Device* device, ID3D12DescriptorHeap* heap, DescriptorHeapType type);
|
|
||||||
~D3D12DescriptorHeap() override;
|
|
||||||
|
|
||||||
DescriptorHeapType GetType() const override { return m_type; }
|
|
||||||
uint32_t GetDescriptorCount() const override { return m_descriptorCount; }
|
|
||||||
void* GetCPUDescriptorHandle(uint32_t index) const override;
|
|
||||||
uint64_t GetGPUDescriptorHandle(uint32_t index) const override;
|
|
||||||
void SetName(const char* name) override;
|
|
||||||
|
|
||||||
ID3D12DescriptorHeap* GetNativeHeap() const { return m_descriptorHeap.Get(); }
|
|
||||||
uint32_t GetDescriptorSize() const { return m_descriptorSize; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_descriptorHeap;
|
|
||||||
DescriptorHeapType m_type;
|
|
||||||
uint32_t m_descriptorCount = 0;
|
|
||||||
uint32_t m_descriptorSize = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12SwapChain : public ISwapChain {
|
|
||||||
public:
|
|
||||||
D3D12SwapChain(D3D12Device* device);
|
|
||||||
~D3D12SwapChain() override;
|
|
||||||
|
|
||||||
bool Initialize(const SwapChainDesc& desc, void* windowHandle) override;
|
|
||||||
void Shutdown() override;
|
|
||||||
bool Present() override;
|
|
||||||
bool Resize(uint32_t width, uint32_t height) override;
|
|
||||||
uint32_t GetCurrentBufferIndex() const override;
|
|
||||||
void* GetBuffer(uint32_t index) override;
|
|
||||||
void* GetCurrentRenderTarget() override;
|
|
||||||
void* GetDepthStencil() override;
|
|
||||||
void SetFullscreen(bool fullscreen) override;
|
|
||||||
bool IsFullscreen() const override;
|
|
||||||
|
|
||||||
IDXGISwapChain3* GetNativeSwapChain() const { return m_swapChain.Get(); }
|
|
||||||
ID3D12Resource* GetBufferResource(uint32_t index) const { return m_buffers[index].Get(); }
|
|
||||||
D3D12DescriptorHeap* GetRTVHeap() const { return m_rtvHeap; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_buffers[16];
|
|
||||||
D3D12DescriptorHeap* m_rtvHeap = nullptr;
|
|
||||||
uint32_t m_bufferCount = 0;
|
|
||||||
bool m_vsync = false;
|
|
||||||
bool m_fullscreen = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12RootSignature : public IRootSignature {
|
|
||||||
public:
|
|
||||||
D3D12RootSignature(D3D12Device* device);
|
|
||||||
~D3D12RootSignature() override;
|
|
||||||
|
|
||||||
bool Initialize(const RootSignatureDesc& desc) override;
|
|
||||||
void SetName(const char* name) override;
|
|
||||||
void* GetNativeRootSignature() const override;
|
|
||||||
|
|
||||||
ID3D12RootSignature* GetNative() const { return m_rootSignature.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> m_rootSignature;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12PipelineState : public IPipelineState {
|
|
||||||
public:
|
|
||||||
D3D12PipelineState(D3D12Device* device);
|
|
||||||
~D3D12PipelineState() override;
|
|
||||||
|
|
||||||
bool Initialize(const PipelineDesc& desc);
|
|
||||||
void SetName(const char* name) override;
|
|
||||||
void* GetNativePipelineState() const override;
|
|
||||||
|
|
||||||
ID3D12PipelineState* GetNative() const { return m_pipelineState.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> m_pipelineState;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12CommandList : public ICommandList {
|
|
||||||
public:
|
|
||||||
D3D12CommandList(D3D12Device* device, ID3D12GraphicsCommandList* list);
|
|
||||||
~D3D12CommandList() override;
|
|
||||||
|
|
||||||
void Reset(void* allocator) override;
|
|
||||||
void Close() override;
|
|
||||||
void SetPipelineState(IPipelineState* pso) override;
|
|
||||||
void SetRootSignature(IRootSignature* signature) override;
|
|
||||||
void SetPrimitiveTopology(PrimitiveTopology topology) override;
|
|
||||||
void SetVertexBuffer(uint32_t slot, IResource* buffer, uint32_t offset, uint32_t stride) override;
|
|
||||||
void SetIndexBuffer(IResource* buffer, uint32_t offset) override;
|
|
||||||
void SetDescriptorHeap(IDescriptorHeap* heap) override;
|
|
||||||
void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override;
|
|
||||||
void SetGraphicsRootConstantBufferView(uint32_t slot, IResource* buffer) override;
|
|
||||||
void SetGraphicsRootConstantBufferViewCBV(uint32_t slot, void* nativeResource) override;
|
|
||||||
void SetGraphicsRoot32BitConstants(uint32_t rootParameterIndex, uint32_t num32BitValues, const void* data, uint32_t destOffsetIn32BitValues) override;
|
|
||||||
void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override;
|
|
||||||
void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) override;
|
|
||||||
void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) override;
|
|
||||||
void Dispatch(uint32_t x, uint32_t y, uint32_t z) override;
|
|
||||||
void SetViewports(const Viewport* viewports, uint32_t count) override;
|
|
||||||
void SetScissorRects(const Rect* rects, uint32_t count) override;
|
|
||||||
void SetRenderTargets(void** targets, uint32_t count, void* depthStencil) override;
|
|
||||||
void ClearRenderTargetView(void* target, const float color[4]) override;
|
|
||||||
void ClearDepthStencilView(void* depth, float depthValue, uint8_t stencil) override;
|
|
||||||
void CopyResource(IResource* dst, const IResource* src) override;
|
|
||||||
void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) override;
|
|
||||||
void ResourceBarrier(IResource* resource, ResourceStateFlag before, ResourceStateFlag after) override;
|
|
||||||
void* GetNativeCommandList() const override;
|
|
||||||
|
|
||||||
ID3D12GraphicsCommandList* GetNative() const { return m_commandList.Get(); }
|
|
||||||
D3D12Device* GetDevice() const { return m_device; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_commandList;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12Resource : public IResource {
|
|
||||||
public:
|
|
||||||
D3D12Resource(D3D12Device* device, ID3D12Resource* resource);
|
|
||||||
~D3D12Resource() override;
|
|
||||||
|
|
||||||
void* GetNativeResource() const override { return m_resource.Get(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_resource.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_resource;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12Device : public IRHIDevice {
|
|
||||||
public:
|
|
||||||
D3D12Device();
|
|
||||||
~D3D12Device() override;
|
|
||||||
|
|
||||||
GraphicsAPI GetAPI() const override { return GraphicsAPI::Direct3D12; }
|
|
||||||
const char* GetAPIName() const override { return "Direct3D 12"; }
|
|
||||||
|
|
||||||
bool Initialize(void* windowHandle, uint32_t width, uint32_t height) override;
|
|
||||||
void Shutdown() override;
|
|
||||||
|
|
||||||
bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) override;
|
|
||||||
bool CreateCommandAllocator(ICommandAllocator** allocator) override;
|
|
||||||
bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) override;
|
|
||||||
bool CreateFence(IFence** fence) override;
|
|
||||||
|
|
||||||
bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) override;
|
|
||||||
|
|
||||||
bool CreateRootSignature(IRootSignature** signature, const RootSignatureDesc& desc) override;
|
|
||||||
bool CreatePipelineState(IPipelineState** pso, const PipelineDesc& desc) override;
|
|
||||||
|
|
||||||
bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) override;
|
|
||||||
|
|
||||||
ICommandQueue* GetCommandQueue() override { return m_commandQueue; }
|
|
||||||
ISwapChain* GetSwapChain() { return m_swapChain; }
|
|
||||||
void* GetNativeDevice() const override { return m_device.Get(); }
|
|
||||||
void* GetNativeAdapter() const override { return m_adapter.Get(); }
|
|
||||||
|
|
||||||
ID3D12Device* GetD3D12Device() const { return m_device.Get(); }
|
|
||||||
IDXGIFactory4* GetDXGIFactory() const { return m_dxgiFactory.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool CreateDXGIDevice(void* windowHandle);
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Device> m_device;
|
|
||||||
Microsoft::WRL::ComPtr<IDXGIAdapter1> m_adapter;
|
|
||||||
Microsoft::WRL::ComPtr<IDXGIFactory4> m_dxgiFactory;
|
|
||||||
|
|
||||||
D3D12CommandQueue* m_commandQueue = nullptr;
|
|
||||||
D3D12SwapChain* m_swapChain = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
#include <Rendering\RenderContext.h>
|
|
||||||
#include <RHI\D3D12\D3D12RHI.h>
|
|
||||||
#include <RHI\D3D12\D3D12Resources.h>
|
|
||||||
|
|
||||||
void EngineLog(const char* msg, ...);
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
RenderContext::RenderContext(D3D12Device* device) : m_device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderContext::~RenderContext() {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderContext::Initialize(uint32_t width, uint32_t height) {
|
|
||||||
m_width = width;
|
|
||||||
m_height = height;
|
|
||||||
|
|
||||||
if (!m_device->CreateCommandAllocator(&m_commandAllocator)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_device->CreateCommandList(&m_commandList, m_commandAllocator)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_device->CreateFence(&m_fence)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_swapChain = m_device->GetSwapChain();
|
|
||||||
if (!m_swapChain) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorHeapDesc dsvHeapDesc = {};
|
|
||||||
dsvHeapDesc.type = DescriptorHeapType::DSV;
|
|
||||||
dsvHeapDesc.count = 1;
|
|
||||||
dsvHeapDesc.shaderVisible = false;
|
|
||||||
if (!m_device->CreateDescriptorHeap((IDescriptorHeap**)&m_dsvHeap, dsvHeapDesc)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CreateDepthStencil(m_device, width, height, Format::D24_UNorm_S8_UInt, &m_depthStencil)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_depthStencil->SetDSVHeap(m_dsvHeap);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::Shutdown() {
|
|
||||||
if (m_fence) {
|
|
||||||
m_fence->Wait(m_fenceValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_commandList) delete m_commandList;
|
|
||||||
if (m_commandAllocator) delete m_commandAllocator;
|
|
||||||
if (m_fence) delete m_fence;
|
|
||||||
if (m_swapChain) delete m_swapChain;
|
|
||||||
if (m_currentRenderTarget) delete m_currentRenderTarget;
|
|
||||||
if (m_depthStencil) delete m_depthStencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::BeginFrame() {
|
|
||||||
EngineLog("BeginFrame: start");
|
|
||||||
|
|
||||||
m_fence->Wait(m_fenceValue);
|
|
||||||
|
|
||||||
m_commandAllocator->Reset();
|
|
||||||
m_commandList->Reset(m_commandAllocator);
|
|
||||||
|
|
||||||
uint32_t bufferIndex = m_swapChain->GetCurrentBufferIndex();
|
|
||||||
EngineLog("BeginFrame: bufferIndex=%u", bufferIndex);
|
|
||||||
|
|
||||||
D3D12CommandList* cmdList = (D3D12CommandList*)m_commandList;
|
|
||||||
ID3D12GraphicsCommandList* d3dCmdList = cmdList->GetNative();
|
|
||||||
|
|
||||||
m_depthStencil->CreateDSV();
|
|
||||||
|
|
||||||
ID3D12Resource* buffer = (ID3D12Resource*)m_swapChain->GetBuffer(bufferIndex);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = buffer;
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
d3dCmdList->ResourceBarrier(1, &barrier);
|
|
||||||
EngineLog("BeginFrame: after ResourceBarrier");
|
|
||||||
|
|
||||||
void* currentRT = m_swapChain->GetCurrentRenderTarget();
|
|
||||||
void* currentDS = m_depthStencil->GetDSV();
|
|
||||||
EngineLog("BeginFrame: RTV=%llu, DSV=%llu", (UINT64)currentRT, (UINT64)currentDS);
|
|
||||||
|
|
||||||
void* targets[] = { currentRT };
|
|
||||||
m_commandList->SetRenderTargets(targets, 1, currentDS);
|
|
||||||
EngineLog("BeginFrame: after SetRenderTargets");
|
|
||||||
|
|
||||||
float clearColor[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
|
||||||
m_commandList->ClearRenderTargetView(currentRT, clearColor);
|
|
||||||
EngineLog("BeginFrame: after ClearRenderTargetView");
|
|
||||||
|
|
||||||
m_commandList->ClearDepthStencilView(currentDS, 1.0f, 0);
|
|
||||||
EngineLog("BeginFrame: after ClearDepthStencilView");
|
|
||||||
|
|
||||||
EngineLog("BeginFrame: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::EndFrame() {
|
|
||||||
D3D12CommandList* cmdList = (D3D12CommandList*)m_commandList;
|
|
||||||
ID3D12GraphicsCommandList* d3dCmdList = cmdList->GetNative();
|
|
||||||
|
|
||||||
uint32_t bufferIndex = m_swapChain->GetCurrentBufferIndex();
|
|
||||||
ID3D12Resource* buffer = (ID3D12Resource*)m_swapChain->GetBuffer(bufferIndex);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = buffer;
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
d3dCmdList->ResourceBarrier(1, &barrier);
|
|
||||||
|
|
||||||
m_commandList->Close();
|
|
||||||
EngineLog("EndFrame: after Close");
|
|
||||||
|
|
||||||
ICommandQueue* queue = m_device->GetCommandQueue();
|
|
||||||
void* cmdListPtr = m_commandList->GetNativeCommandList();
|
|
||||||
queue->ExecuteCommandLists(&cmdListPtr, 1);
|
|
||||||
EngineLog("EndFrame: after Execute");
|
|
||||||
|
|
||||||
EngineLog("EndFrame: before Signal");
|
|
||||||
m_fenceValue++;
|
|
||||||
D3D12Fence* d3d12Fence = static_cast<D3D12Fence*>(m_fence);
|
|
||||||
queue->Signal(d3d12Fence->GetNativeFence(), m_fenceValue);
|
|
||||||
EngineLog("EndFrame: after Signal");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::SetViewport(float width, float height) {
|
|
||||||
EngineLog("SetViewport: start");
|
|
||||||
Viewport viewport = {};
|
|
||||||
viewport.topLeftX = 0;
|
|
||||||
viewport.topLeftY = 0;
|
|
||||||
viewport.width = width;
|
|
||||||
viewport.height = height;
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 1.0f;
|
|
||||||
m_commandList->SetViewports(&viewport, 1);
|
|
||||||
EngineLog("SetViewport: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::SetScissor(int32_t width, int32_t height) {
|
|
||||||
EngineLog("SetScissor: start");
|
|
||||||
Rect scissor = {};
|
|
||||||
scissor.left = 0;
|
|
||||||
scissor.top = 0;
|
|
||||||
scissor.right = width;
|
|
||||||
scissor.bottom = height;
|
|
||||||
m_commandList->SetScissorRects(&scissor, 1);
|
|
||||||
EngineLog("SetScissor: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::ClearRenderTarget(const float color[4]) {
|
|
||||||
EngineLog("ClearRT: start");
|
|
||||||
void* rtv = m_swapChain->GetCurrentRenderTarget();
|
|
||||||
void* ds = m_depthStencil->GetDSV();
|
|
||||||
void* targets[] = { rtv };
|
|
||||||
m_commandList->SetRenderTargets(targets, 1, ds);
|
|
||||||
EngineLog("ClearRT: rtv=%p", rtv);
|
|
||||||
m_commandList->ClearRenderTargetView(rtv, color);
|
|
||||||
EngineLog("ClearRT: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::ClearDepthStencil() {
|
|
||||||
//EngineLog("ClearDS: start");
|
|
||||||
//EngineLog("ClearDS: m_depthStencil=%p", m_depthStencil);
|
|
||||||
//m_depthStencil->CreateDSV();
|
|
||||||
//EngineLog("ClearDS: after CreateDSV");
|
|
||||||
//void* dsv = m_depthStencil->GetDSV();
|
|
||||||
//EngineLog("ClearDS: dsv=%p", dsv);
|
|
||||||
//m_commandList->ClearDepthStencilView(dsv, 1.0f, 0);
|
|
||||||
//EngineLog("ClearDS: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderContext::Present() {
|
|
||||||
m_swapChain->Present();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#include "D3D12Resources.h"
|
|
||||||
#include "Rendering\RenderTarget.h"
|
|
||||||
|
|
||||||
void EngineLog(const char* msg, ...);
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
void D3D12DepthStencil::CreateDSV() {
|
|
||||||
EngineLog("CreateDSV: start, m_device=%p, m_resource=%p", m_device, m_resource.Get());
|
|
||||||
if (m_dsvHandle.ptr != 0) {
|
|
||||||
EngineLog("CreateDSV: already created");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!m_dsvHeap) {
|
|
||||||
EngineLog("CreateDSV: ERROR - no DSV heap!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EngineLog("CreateDSV: calling CreateDepthStencilView");
|
|
||||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
|
|
||||||
dsvDesc.Format = FormatToDXGIFormat(m_desc.format);
|
|
||||||
EngineLog("CreateDSV: format=%d", dsvDesc.Format);
|
|
||||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE heapStart = m_dsvHeap->GetNativeHeap()->GetCPUDescriptorHandleForHeapStart();
|
|
||||||
m_dsvHandle = heapStart;
|
|
||||||
|
|
||||||
m_device->GetD3D12Device()->CreateDepthStencilView(m_resource.Get(), &dsvDesc, m_dsvHandle);
|
|
||||||
EngineLog("CreateDSV: done, handle=%llu", (UINT64)m_dsvHandle.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12RenderTarget::CreateRTV() {
|
|
||||||
EngineLog("CreateRTV: start, m_device=%p", m_device);
|
|
||||||
if (m_rtvHandle.ptr != 0) return;
|
|
||||||
ID3D12Device* d3dDevice = m_device->GetD3D12Device();
|
|
||||||
EngineLog("CreateRTV: d3dDevice=%p, m_resource=%p", d3dDevice, m_resource.Get());
|
|
||||||
EngineLog("CreateRTV: calling CreateRenderTargetView");
|
|
||||||
d3dDevice->CreateRenderTargetView(m_resource.Get(), nullptr, m_rtvHandle);
|
|
||||||
EngineLog("CreateRTV: done");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateDepthStencil(D3D12Device* device, uint32_t width, uint32_t height, Format format, IDepthStencil** outDepthStencil) {
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
|
||||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
||||||
resourceDesc.Width = width;
|
|
||||||
resourceDesc.Height = height;
|
|
||||||
resourceDesc.DepthOrArraySize = 1;
|
|
||||||
resourceDesc.MipLevels = 1;
|
|
||||||
resourceDesc.Format = FormatToDXGIFormat(format);
|
|
||||||
resourceDesc.SampleDesc.Count = 1;
|
|
||||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
|
||||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
|
||||||
|
|
||||||
D3D12_CLEAR_VALUE clearValue = {};
|
|
||||||
clearValue.Format = FormatToDXGIFormat(format);
|
|
||||||
clearValue.DepthStencil.Depth = 1.0f;
|
|
||||||
clearValue.DepthStencil.Stencil = 0;
|
|
||||||
|
|
||||||
ID3D12Resource* resource = nullptr;
|
|
||||||
HRESULT hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&heapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, IID_PPV_ARGS(&resource));
|
|
||||||
if (FAILED(hr)) return false;
|
|
||||||
|
|
||||||
TextureDesc desc = {};
|
|
||||||
desc.width = width;
|
|
||||||
desc.height = height;
|
|
||||||
desc.format = format;
|
|
||||||
desc.depthStencil = true;
|
|
||||||
|
|
||||||
*outDepthStencil = new D3D12DepthStencil(device, resource, desc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateRenderTargetFromSwapChain(D3D12Device* device, D3D12SwapChain* swapChain, uint32_t bufferIndex, IRenderTarget** outRenderTarget) {
|
|
||||||
ID3D12Resource* resource = swapChain->GetBufferResource(bufferIndex);
|
|
||||||
|
|
||||||
TextureDesc desc = {};
|
|
||||||
desc.width = 0;
|
|
||||||
desc.height = 0;
|
|
||||||
desc.format = Format::R8G8B8A8_UNorm;
|
|
||||||
desc.renderTarget = true;
|
|
||||||
|
|
||||||
*outRenderTarget = new D3D12RenderTarget(device, resource, desc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
#include "D3D12Resources.h"
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
D3D12Buffer::D3D12Buffer(D3D12Device* device, ID3D12Resource* resource, const BufferDesc& desc)
|
|
||||||
: m_device(device), m_resource(resource), m_desc(desc) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Buffer::~D3D12Buffer() {
|
|
||||||
m_resource.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12Buffer::Map() {
|
|
||||||
void* data = nullptr;
|
|
||||||
D3D12_RANGE range = { 0, (SIZE_T)m_desc.size };
|
|
||||||
m_resource->Map(0, &range, &data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Buffer::Unmap() {
|
|
||||||
m_resource->Unmap(0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12VertexBuffer::D3D12VertexBuffer(D3D12Buffer* buffer) : m_buffer(buffer) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12VertexBuffer::~D3D12VertexBuffer() {
|
|
||||||
delete m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12IndexBuffer::D3D12IndexBuffer(D3D12Buffer* buffer) : m_buffer(buffer) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12IndexBuffer::~D3D12IndexBuffer() {
|
|
||||||
delete m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12ConstantBuffer::D3D12ConstantBuffer(D3D12Buffer* buffer) : m_buffer(buffer) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12ConstantBuffer::~D3D12ConstantBuffer() {
|
|
||||||
delete m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Texture2D::D3D12Texture2D(D3D12Device* device, ID3D12Resource* resource, const TextureDesc& desc)
|
|
||||||
: m_device(device), m_resource(resource), m_desc(desc) {
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12Texture2D::~D3D12Texture2D() {
|
|
||||||
m_resource.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Texture2D::CreateSRV() {
|
|
||||||
if (m_hasSRV) return;
|
|
||||||
|
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
||||||
srvDesc.Format = FormatToDXGIFormat(m_desc.format);
|
|
||||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
|
||||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
|
||||||
srvDesc.Texture2D.MipLevels = m_desc.mipLevels;
|
|
||||||
|
|
||||||
m_device->GetD3D12Device()->CreateShaderResourceView(m_resource.Get(), &srvDesc, m_srvHandle);
|
|
||||||
m_hasSRV = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12Texture2D::GetSRV() {
|
|
||||||
return (void*)m_srvHandle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Texture2D::CreateRTV() {
|
|
||||||
if (m_hasRTV) return;
|
|
||||||
|
|
||||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
|
||||||
rtvDesc.Format = FormatToDXGIFormat(m_desc.format);
|
|
||||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
|
||||||
|
|
||||||
m_device->GetD3D12Device()->CreateRenderTargetView(m_resource.Get(), &rtvDesc, m_rtvHandle);
|
|
||||||
m_hasRTV = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12Texture2D::GetRTV() {
|
|
||||||
return (void*)m_rtvHandle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Texture2D::CreateDSV() {
|
|
||||||
if (m_hasDSV) return;
|
|
||||||
|
|
||||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
|
|
||||||
dsvDesc.Format = FormatToDXGIFormat(m_desc.format);
|
|
||||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
|
||||||
|
|
||||||
m_device->GetD3D12Device()->CreateDepthStencilView(m_resource.Get(), &dsvDesc, m_dsvHandle);
|
|
||||||
m_hasDSV = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* D3D12Texture2D::GetDSV() {
|
|
||||||
return (void*)m_dsvHandle.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateVertexBuffer(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* data, uint64_t size, uint32_t stride, IVertexBuffer** outBuffer) {
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
|
||||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
||||||
resourceDesc.Width = size;
|
|
||||||
resourceDesc.Height = 1;
|
|
||||||
resourceDesc.DepthOrArraySize = 1;
|
|
||||||
resourceDesc.MipLevels = 1;
|
|
||||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
||||||
resourceDesc.SampleDesc.Count = 1;
|
|
||||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
|
|
||||||
ID3D12Resource* bufferResource = nullptr;
|
|
||||||
HRESULT hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&heapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&bufferResource));
|
|
||||||
if (FAILED(hr)) return false;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC bufferDesc = bufferResource->GetDesc();
|
|
||||||
UINT64 memorySize = 0;
|
|
||||||
UINT64 rowSize = 0;
|
|
||||||
UINT rowCount = 0;
|
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
|
||||||
device->GetD3D12Device()->GetCopyableFootprints(&bufferDesc, 0, 1, 0, &footprint, &rowCount, &rowSize, &memorySize);
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES uploadHeapProps = {};
|
|
||||||
uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
|
|
||||||
ID3D12Resource* uploadResource = nullptr;
|
|
||||||
hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&uploadHeapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadResource));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
bufferResource->Release();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8* uploadData = nullptr;
|
|
||||||
uploadResource->Map(0, nullptr, (void**)&uploadData);
|
|
||||||
|
|
||||||
UINT8* dst = uploadData + footprint.Offset;
|
|
||||||
const UINT8* src = (const UINT8*)data;
|
|
||||||
for (UINT i = 0; i < rowCount; i++) {
|
|
||||||
memcpy(dst + footprint.Footprint.RowPitch * i, src + rowSize * i, (SIZE_T)rowSize);
|
|
||||||
}
|
|
||||||
uploadResource->Unmap(0, nullptr);
|
|
||||||
|
|
||||||
D3D12CommandList* d3dCmdList = static_cast<D3D12CommandList*>(commandList);
|
|
||||||
d3dCmdList->GetNative()->CopyBufferRegion(bufferResource, 0, uploadResource, 0, size);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = bufferResource;
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
d3dCmdList->GetNative()->ResourceBarrier(1, &barrier);
|
|
||||||
|
|
||||||
uploadResource->Release();
|
|
||||||
|
|
||||||
BufferDesc bufferDesc2 = {};
|
|
||||||
bufferDesc2.size = size;
|
|
||||||
bufferDesc2.stride = stride;
|
|
||||||
|
|
||||||
D3D12Buffer* buffer = new D3D12Buffer(device, bufferResource, bufferDesc2);
|
|
||||||
*outBuffer = new D3D12VertexBuffer(buffer);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateIndexBuffer(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* data, uint64_t size, IIndexBuffer** outBuffer) {
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
|
||||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
||||||
resourceDesc.Width = size;
|
|
||||||
resourceDesc.Height = 1;
|
|
||||||
resourceDesc.DepthOrArraySize = 1;
|
|
||||||
resourceDesc.MipLevels = 1;
|
|
||||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
||||||
resourceDesc.SampleDesc.Count = 1;
|
|
||||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
|
|
||||||
ID3D12Resource* bufferResource = nullptr;
|
|
||||||
HRESULT hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&heapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&bufferResource));
|
|
||||||
if (FAILED(hr)) return false;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC bufferDesc = bufferResource->GetDesc();
|
|
||||||
UINT64 memorySize = 0;
|
|
||||||
UINT64 rowSize = 0;
|
|
||||||
UINT rowCount = 0;
|
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
|
||||||
device->GetD3D12Device()->GetCopyableFootprints(&bufferDesc, 0, 1, 0, &footprint, &rowCount, &rowSize, &memorySize);
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES uploadHeapProps = {};
|
|
||||||
uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
|
|
||||||
ID3D12Resource* uploadResource = nullptr;
|
|
||||||
hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&uploadHeapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadResource));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
bufferResource->Release();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8* uploadData = nullptr;
|
|
||||||
uploadResource->Map(0, nullptr, (void**)&uploadData);
|
|
||||||
|
|
||||||
memcpy(uploadData + footprint.Offset, data, (SIZE_T)size);
|
|
||||||
uploadResource->Unmap(0, nullptr);
|
|
||||||
|
|
||||||
D3D12CommandList* d3dCmdList = static_cast<D3D12CommandList*>(commandList);
|
|
||||||
d3dCmdList->GetNative()->CopyBufferRegion(bufferResource, 0, uploadResource, 0, size);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = bufferResource;
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
d3dCmdList->GetNative()->ResourceBarrier(1, &barrier);
|
|
||||||
|
|
||||||
uploadResource->Release();
|
|
||||||
|
|
||||||
BufferDesc bufferDesc2 = {};
|
|
||||||
bufferDesc2.size = size;
|
|
||||||
bufferDesc2.stride = 4;
|
|
||||||
|
|
||||||
D3D12Buffer* buffer = new D3D12Buffer(device, bufferResource, bufferDesc2);
|
|
||||||
*outBuffer = new D3D12IndexBuffer(buffer);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateConstantBuffer(D3D12Device* device, uint64_t size, IConstantBuffer** outBuffer) {
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
|
||||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
||||||
resourceDesc.Width = size;
|
|
||||||
resourceDesc.Height = 1;
|
|
||||||
resourceDesc.DepthOrArraySize = 1;
|
|
||||||
resourceDesc.MipLevels = 1;
|
|
||||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
||||||
resourceDesc.SampleDesc.Count = 1;
|
|
||||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
|
|
||||||
ID3D12Resource* bufferResource = nullptr;
|
|
||||||
HRESULT hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&heapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bufferResource));
|
|
||||||
if (FAILED(hr)) return false;
|
|
||||||
|
|
||||||
BufferDesc bufferDesc = {};
|
|
||||||
bufferDesc.size = size;
|
|
||||||
bufferDesc.stride = (uint32_t)size;
|
|
||||||
bufferDesc.cpuAccessible = true;
|
|
||||||
|
|
||||||
D3D12Buffer* buffer = new D3D12Buffer(device, bufferResource, bufferDesc);
|
|
||||||
*outBuffer = new D3D12ConstantBuffer(buffer);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateTexture2D(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* pixels, uint32_t width, uint32_t height, Format format, ITexture2D** outTexture) {
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
|
||||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
||||||
resourceDesc.Width = width;
|
|
||||||
resourceDesc.Height = height;
|
|
||||||
resourceDesc.DepthOrArraySize = 1;
|
|
||||||
resourceDesc.MipLevels = 1;
|
|
||||||
resourceDesc.Format = FormatToDXGIFormat(format);
|
|
||||||
resourceDesc.SampleDesc.Count = 1;
|
|
||||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
|
||||||
|
|
||||||
ID3D12Resource* textureResource = nullptr;
|
|
||||||
HRESULT hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&heapProps, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&textureResource));
|
|
||||||
if (FAILED(hr)) return false;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC texDesc = textureResource->GetDesc();
|
|
||||||
UINT64 memorySize = 0;
|
|
||||||
UINT64 rowSize = 0;
|
|
||||||
UINT rowCount = 0;
|
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
|
||||||
device->GetD3D12Device()->GetCopyableFootprints(&texDesc, 0, 1, 0, &footprint, &rowCount, &rowSize, &memorySize);
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES uploadHeapProps = {};
|
|
||||||
uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC uploadDesc = {};
|
|
||||||
uploadDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
||||||
uploadDesc.Width = memorySize;
|
|
||||||
uploadDesc.Height = 1;
|
|
||||||
uploadDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
|
|
||||||
ID3D12Resource* uploadResource = nullptr;
|
|
||||||
hr = device->GetD3D12Device()->CreateCommittedResource(
|
|
||||||
&uploadHeapProps, D3D12_HEAP_FLAG_NONE, &uploadDesc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadResource));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
textureResource->Release();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8* uploadData = nullptr;
|
|
||||||
uploadResource->Map(0, nullptr, (void**)&uploadData);
|
|
||||||
|
|
||||||
UINT8* dst = uploadData + footprint.Offset;
|
|
||||||
const UINT8* src = (const UINT8*)pixels;
|
|
||||||
for (UINT i = 0; i < rowCount; i++) {
|
|
||||||
memcpy(dst + footprint.Footprint.RowPitch * i, src + rowSize * i, (SIZE_T)rowSize);
|
|
||||||
}
|
|
||||||
uploadResource->Unmap(0, nullptr);
|
|
||||||
|
|
||||||
D3D12CommandList* d3dCmdList = static_cast<D3D12CommandList*>(commandList);
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION dstLoc = {};
|
|
||||||
dstLoc.pResource = textureResource;
|
|
||||||
dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
||||||
dstLoc.SubresourceIndex = 0;
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION srcLoc = {};
|
|
||||||
srcLoc.pResource = uploadResource;
|
|
||||||
srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
||||||
srcLoc.PlacedFootprint = footprint;
|
|
||||||
|
|
||||||
d3dCmdList->GetNative()->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr);
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = textureResource;
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
d3dCmdList->GetNative()->ResourceBarrier(1, &barrier);
|
|
||||||
|
|
||||||
uploadResource->Release();
|
|
||||||
|
|
||||||
TextureDesc texDesc2 = {};
|
|
||||||
texDesc2.width = width;
|
|
||||||
texDesc2.height = height;
|
|
||||||
texDesc2.format = format;
|
|
||||||
|
|
||||||
D3D12Texture2D* texture = new D3D12Texture2D(device, textureResource, texDesc2);
|
|
||||||
*outTexture = texture;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateConstantBuffer(IConstantBuffer* buffer, const void* data, uint64_t size) {
|
|
||||||
D3D12ConstantBuffer* d3dBuffer = static_cast<D3D12ConstantBuffer*>(buffer);
|
|
||||||
void* mapped = d3dBuffer->Map();
|
|
||||||
if (mapped) {
|
|
||||||
memcpy(mapped, data, (SIZE_T)size);
|
|
||||||
d3dBuffer->Unmap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Rendering\Resources.h>
|
|
||||||
#include <Rendering\RenderTarget.h>
|
|
||||||
#include <RHI\D3D12\D3D12RHI.h>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
class D3D12Buffer : public IBuffer {
|
|
||||||
public:
|
|
||||||
D3D12Buffer(D3D12Device* device, ID3D12Resource* resource, const BufferDesc& desc);
|
|
||||||
~D3D12Buffer() override;
|
|
||||||
|
|
||||||
const BufferDesc& GetDesc() const override { return m_desc; }
|
|
||||||
void* Map() override;
|
|
||||||
void Unmap() override;
|
|
||||||
void* GetNativeResource() const override { return m_resource.Get(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_resource.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_resource;
|
|
||||||
BufferDesc m_desc;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12VertexBuffer : public IVertexBuffer {
|
|
||||||
public:
|
|
||||||
D3D12VertexBuffer(D3D12Buffer* buffer);
|
|
||||||
~D3D12VertexBuffer() override;
|
|
||||||
|
|
||||||
const BufferDesc& GetDesc() const override { return m_buffer->GetDesc(); }
|
|
||||||
void* Map() override { return m_buffer->Map(); }
|
|
||||||
void Unmap() override { m_buffer->Unmap(); }
|
|
||||||
void* GetNativeResource() const override { return m_buffer->GetNativeResource(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_buffer->GetNative(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Buffer* m_buffer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12IndexBuffer : public IIndexBuffer {
|
|
||||||
public:
|
|
||||||
D3D12IndexBuffer(D3D12Buffer* buffer);
|
|
||||||
~D3D12IndexBuffer() override;
|
|
||||||
|
|
||||||
const BufferDesc& GetDesc() const override { return m_buffer->GetDesc(); }
|
|
||||||
void* Map() override { return m_buffer->Map(); }
|
|
||||||
void Unmap() override { m_buffer->Unmap(); }
|
|
||||||
void* GetNativeResource() const override { return m_buffer->GetNativeResource(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_buffer->GetNative(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Buffer* m_buffer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12ConstantBuffer : public IConstantBuffer {
|
|
||||||
public:
|
|
||||||
D3D12ConstantBuffer(D3D12Buffer* buffer);
|
|
||||||
~D3D12ConstantBuffer() override;
|
|
||||||
|
|
||||||
const BufferDesc& GetDesc() const override { return m_buffer->GetDesc(); }
|
|
||||||
void* Map() override { return m_buffer->Map(); }
|
|
||||||
void Unmap() override { return m_buffer->Unmap(); }
|
|
||||||
void* GetNativeResource() const override { return m_buffer->GetNativeResource(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_buffer->GetNative(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Buffer* m_buffer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12Texture2D : public ITexture2D {
|
|
||||||
public:
|
|
||||||
D3D12Texture2D(D3D12Device* device, ID3D12Resource* resource, const TextureDesc& desc);
|
|
||||||
~D3D12Texture2D() override;
|
|
||||||
|
|
||||||
const TextureDesc& GetDesc() const override { return m_desc; }
|
|
||||||
void CreateSRV() override;
|
|
||||||
void* GetSRV() override;
|
|
||||||
void CreateRTV() override;
|
|
||||||
void* GetRTV() override;
|
|
||||||
void CreateDSV() override;
|
|
||||||
void* GetDSV() override;
|
|
||||||
void* GetNativeResource() const override { return m_resource.Get(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_resource.Get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_resource;
|
|
||||||
TextureDesc m_desc;
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE m_srvHandle = {};
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE m_rtvHandle = {};
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE m_dsvHandle = {};
|
|
||||||
bool m_hasSRV = false;
|
|
||||||
bool m_hasRTV = false;
|
|
||||||
bool m_hasDSV = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CreateVertexBuffer(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* data, uint64_t size, uint32_t stride, IVertexBuffer** outBuffer);
|
|
||||||
|
|
||||||
bool CreateIndexBuffer(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* data, uint64_t size, IIndexBuffer** outBuffer);
|
|
||||||
|
|
||||||
bool CreateConstantBuffer(D3D12Device* device, uint64_t size, IConstantBuffer** outBuffer);
|
|
||||||
|
|
||||||
bool CreateTexture2D(D3D12Device* device, ICommandList* commandList,
|
|
||||||
const void* pixels, uint32_t width, uint32_t height, Format format, ITexture2D** outTexture);
|
|
||||||
|
|
||||||
void UpdateConstantBuffer(IConstantBuffer* buffer, const void* data, uint64_t size);
|
|
||||||
|
|
||||||
class D3D12DepthStencil : public IDepthStencil {
|
|
||||||
public:
|
|
||||||
D3D12DepthStencil(D3D12Device* device, ID3D12Resource* resource, const TextureDesc& desc)
|
|
||||||
: m_device(device), m_resource(resource), m_desc(desc) {}
|
|
||||||
|
|
||||||
~D3D12DepthStencil() override {
|
|
||||||
m_resource.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextureDesc& GetDesc() const override { return m_desc; }
|
|
||||||
void* GetNativeResource() const override { return m_resource.Get(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_resource.Get(); }
|
|
||||||
|
|
||||||
void SetDSVHeap(void* heap) override { m_dsvHeap = (D3D12DescriptorHeap*)heap; }
|
|
||||||
|
|
||||||
void CreateSRV() override {}
|
|
||||||
void* GetSRV() override { return nullptr; }
|
|
||||||
void CreateRTV() override {}
|
|
||||||
void* GetRTV() override { return nullptr; }
|
|
||||||
void CreateDSV() override;
|
|
||||||
void* GetDSV() override { return (void*)m_dsvHandle.ptr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_resource;
|
|
||||||
TextureDesc m_desc;
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE m_dsvHandle = {};
|
|
||||||
D3D12DescriptorHeap* m_dsvHeap = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12RenderTarget : public IRenderTarget {
|
|
||||||
public:
|
|
||||||
D3D12RenderTarget(D3D12Device* device, ID3D12Resource* resource, const TextureDesc& desc)
|
|
||||||
: m_device(device), m_resource(resource), m_desc(desc) {}
|
|
||||||
|
|
||||||
~D3D12RenderTarget() override {
|
|
||||||
m_resource.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextureDesc& GetDesc() const override { return m_desc; }
|
|
||||||
void* GetNativeResource() const override { return m_resource.Get(); }
|
|
||||||
ID3D12Resource* GetNative() const { return m_resource.Get(); }
|
|
||||||
|
|
||||||
void CreateSRV() override {}
|
|
||||||
void* GetSRV() override { return nullptr; }
|
|
||||||
void CreateRTV() override;
|
|
||||||
void* GetRTV() override { return (void*)m_rtvHandle.ptr; }
|
|
||||||
void CreateDSV() override {}
|
|
||||||
void* GetDSV() override { return nullptr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
D3D12Device* m_device = nullptr;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D12Resource> m_resource;
|
|
||||||
TextureDesc m_desc;
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE m_rtvHandle = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CreateDepthStencil(D3D12Device* device, uint32_t width, uint32_t height, Format format, IDepthStencil** outDepthStencil);
|
|
||||||
bool CreateRenderTargetFromSwapChain(D3D12Device* device, D3D12SwapChain* swapChain, uint32_t bufferIndex, IRenderTarget** outRenderTarget);
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include <Rendering\Shader.h>
|
|
||||||
#include <d3dcompiler.h>
|
|
||||||
#include <wrl/client.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
bool CompileShader(const char* filePath, const char* entryPoint, const char* target, ShaderBytecode& outBytecode) {
|
|
||||||
UINT flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
|
||||||
|
|
||||||
ID3DBlob* shaderBuffer = nullptr;
|
|
||||||
ID3DBlob* errorBuffer = nullptr;
|
|
||||||
|
|
||||||
HRESULT hr = D3DCompileFromFile(
|
|
||||||
std::wstring(filePath, filePath + strlen(filePath)).c_str(),
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
entryPoint,
|
|
||||||
target,
|
|
||||||
flags,
|
|
||||||
0,
|
|
||||||
&shaderBuffer,
|
|
||||||
&errorBuffer);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
if (errorBuffer) {
|
|
||||||
OutputDebugStringA((const char*)errorBuffer->GetBufferPointer());
|
|
||||||
errorBuffer->Release();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
outBytecode.bytecode = shaderBuffer->GetBufferPointer();
|
|
||||||
outBytecode.size = shaderBuffer->GetBufferSize();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
#include <Rendering\StaticMeshComponent.h>
|
|
||||||
#include <RHI\D3D12\D3D12RHI.h>
|
|
||||||
#include <RHI\D3D12\D3D12Resources.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
namespace XCEngine {
|
|
||||||
namespace RHI {
|
|
||||||
|
|
||||||
StaticMeshComponent::StaticMeshComponent() {
|
|
||||||
}
|
|
||||||
|
|
||||||
StaticMeshComponent::~StaticMeshComponent() {
|
|
||||||
if (m_vertexBuffer) {
|
|
||||||
delete m_vertexBuffer;
|
|
||||||
}
|
|
||||||
for (auto& pair : m_subMeshes) {
|
|
||||||
delete pair.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StaticMeshComponent::Initialize(ICommandList* commandList, const char* filePath) {
|
|
||||||
D3D12CommandList* d3d12CmdList = static_cast<D3D12CommandList*>(commandList);
|
|
||||||
D3D12Device* device = d3d12CmdList->GetDevice();
|
|
||||||
|
|
||||||
FILE* file = nullptr;
|
|
||||||
if (fopen_s(&file, filePath, "rb") != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vertexCount = 0;
|
|
||||||
fread(&vertexCount, 4, 1, file);
|
|
||||||
m_vertexCount = vertexCount;
|
|
||||||
|
|
||||||
MeshVertex* vertices = new MeshVertex[vertexCount];
|
|
||||||
fread(vertices, sizeof(MeshVertex), vertexCount, file);
|
|
||||||
|
|
||||||
CreateVertexBuffer(device, commandList, vertices, sizeof(MeshVertex) * vertexCount, sizeof(MeshVertex), &m_vertexBuffer);
|
|
||||||
|
|
||||||
delete[] vertices;
|
|
||||||
|
|
||||||
while (!feof(file)) {
|
|
||||||
int nameLength = 0;
|
|
||||||
fread(&nameLength, 4, 1, file);
|
|
||||||
if (feof(file)) break;
|
|
||||||
|
|
||||||
char name[256] = {0};
|
|
||||||
fread(name, 1, nameLength, file);
|
|
||||||
|
|
||||||
int indexCount = 0;
|
|
||||||
fread(&indexCount, 4, 1, file);
|
|
||||||
|
|
||||||
uint32_t* indices = new uint32_t[indexCount];
|
|
||||||
fread(indices, sizeof(uint32_t), indexCount, file);
|
|
||||||
|
|
||||||
IIndexBuffer* indexBuffer = nullptr;
|
|
||||||
CreateIndexBuffer(device, commandList, indices, sizeof(uint32_t) * indexCount, &indexBuffer);
|
|
||||||
|
|
||||||
delete[] indices;
|
|
||||||
|
|
||||||
SubMesh* submesh = new SubMesh();
|
|
||||||
submesh->indexBuffer = indexBuffer;
|
|
||||||
submesh->indexCount = indexCount;
|
|
||||||
m_subMeshes[std::string(name)] = submesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StaticMeshComponent::Render(ICommandList* commandList) {
|
|
||||||
if (!m_vertexBuffer) return;
|
|
||||||
|
|
||||||
commandList->SetVertexBuffer(0, m_vertexBuffer, 0, sizeof(MeshVertex));
|
|
||||||
|
|
||||||
if (m_subMeshes.empty()) {
|
|
||||||
commandList->DrawInstanced(m_vertexCount, 1, 0, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (auto& pair : m_subMeshes) {
|
|
||||||
SubMesh* submesh = pair.second;
|
|
||||||
commandList->SetIndexBuffer(submesh->indexBuffer, 0);
|
|
||||||
commandList->DrawIndexedInstanced(submesh->indexCount, 1, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace RHI
|
|
||||||
} // namespace XCEngine
|
|
||||||
@@ -43,6 +43,7 @@ add_subdirectory(containers)
|
|||||||
add_subdirectory(memory)
|
add_subdirectory(memory)
|
||||||
add_subdirectory(threading)
|
add_subdirectory(threading)
|
||||||
add_subdirectory(debug)
|
add_subdirectory(debug)
|
||||||
|
add_subdirectory(D3D12)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Test Summary
|
# Test Summary
|
||||||
|
|||||||
26
tests/D3D12/CMakeLists.txt
Normal file
26
tests/D3D12/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
project(D3D12)
|
||||||
|
|
||||||
|
add_executable(D3D12
|
||||||
|
WIN32
|
||||||
|
main.cpp
|
||||||
|
stbi/stb_image.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(D3D12 PRIVATE
|
||||||
|
UNICODE
|
||||||
|
_UNICODE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(D3D12 PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}/tests/D3D12
|
||||||
|
${CMAKE_SOURCE_DIR}/tests/D3D12/stbi
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(D3D12 PRIVATE
|
||||||
|
d3d12
|
||||||
|
dxgi
|
||||||
|
d3dcompiler
|
||||||
|
winmm
|
||||||
|
)
|
||||||
319
tests/D3D12/RHI/Enums.h
Normal file
319
tests/D3D12/RHI/Enums.h
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace RHI {
|
||||||
|
|
||||||
|
enum class ShaderType : uint8_t {
|
||||||
|
Vertex,
|
||||||
|
Hull,
|
||||||
|
Domain,
|
||||||
|
Geometry,
|
||||||
|
Pixel,
|
||||||
|
Compute,
|
||||||
|
Amplification,
|
||||||
|
Mesh,
|
||||||
|
Library
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CullMode : uint8_t {
|
||||||
|
None = 1,
|
||||||
|
Front = 2,
|
||||||
|
Back = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FillMode : uint8_t {
|
||||||
|
Wireframe = 2,
|
||||||
|
Solid = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendOp : uint8_t {
|
||||||
|
Add = 1,
|
||||||
|
Subtract = 2,
|
||||||
|
ReverseSubtract = 3,
|
||||||
|
Min = 4,
|
||||||
|
Max = 5,
|
||||||
|
LogicalClear = 8,
|
||||||
|
LogicalSet = 9,
|
||||||
|
LogicalCopy = 10,
|
||||||
|
LogicalCopyInverted = 11,
|
||||||
|
LogicalNoop = 12,
|
||||||
|
LogicalInvert = 13,
|
||||||
|
LogicalAnd = 14,
|
||||||
|
LogicalNand = 15,
|
||||||
|
LogicalOr = 16,
|
||||||
|
LogicalNor = 17,
|
||||||
|
LogicalXor = 18,
|
||||||
|
LogicalEquiv = 19,
|
||||||
|
LogicalAndReverse = 20,
|
||||||
|
LogicalAndInverted = 21,
|
||||||
|
LogicalOrReverse = 22,
|
||||||
|
LogicalOrInverted = 23
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendFactor : uint8_t {
|
||||||
|
Zero = 0,
|
||||||
|
One = 1,
|
||||||
|
SrcColor = 2,
|
||||||
|
InvSrcColor = 3,
|
||||||
|
SrcAlpha = 4,
|
||||||
|
InvSrcAlpha = 5,
|
||||||
|
DstAlpha = 6,
|
||||||
|
InvDstAlpha = 7,
|
||||||
|
DstColor = 8,
|
||||||
|
InvDstColor = 9,
|
||||||
|
SrcAlphaSat = 10,
|
||||||
|
BlendFactor = 11,
|
||||||
|
InvBlendFactor = 12,
|
||||||
|
Src1Color = 13,
|
||||||
|
InvSrc1Color = 14,
|
||||||
|
Src1Alpha = 15,
|
||||||
|
InvSrc1Alpha = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ComparisonFunc : uint8_t {
|
||||||
|
Never = 1,
|
||||||
|
Less = 2,
|
||||||
|
Equal = 3,
|
||||||
|
LessEqual = 4,
|
||||||
|
Greater = 5,
|
||||||
|
NotEqual = 6,
|
||||||
|
GreaterEqual = 7,
|
||||||
|
Always = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class StencilOp : uint8_t {
|
||||||
|
Keep = 1,
|
||||||
|
Zero = 2,
|
||||||
|
Replace = 3,
|
||||||
|
IncrSat = 4,
|
||||||
|
DecrSat = 5,
|
||||||
|
Invert = 6,
|
||||||
|
Incr = 7,
|
||||||
|
Decr = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureType : uint8_t {
|
||||||
|
Texture1D,
|
||||||
|
Texture2D,
|
||||||
|
Texture2DArray,
|
||||||
|
Texture3D,
|
||||||
|
TextureCube,
|
||||||
|
TextureCubeArray
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BufferType : uint8_t {
|
||||||
|
Vertex,
|
||||||
|
Index,
|
||||||
|
Constant,
|
||||||
|
ReadBack,
|
||||||
|
Indirect,
|
||||||
|
RaytracingAccelerationStructure,
|
||||||
|
ShaderBindingTable
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DescriptorType : uint8_t {
|
||||||
|
CBV,
|
||||||
|
SRV,
|
||||||
|
UAV,
|
||||||
|
Sampler,
|
||||||
|
RTV,
|
||||||
|
DSV
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineType : uint8_t {
|
||||||
|
Graphics,
|
||||||
|
Compute,
|
||||||
|
Raytracing
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CommandQueueType : uint8_t {
|
||||||
|
Direct,
|
||||||
|
Compute,
|
||||||
|
Copy
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LoadAction : uint8_t {
|
||||||
|
Undefined = 0,
|
||||||
|
Load = 1,
|
||||||
|
Clear = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class StoreAction : uint8_t {
|
||||||
|
Undefined = 0,
|
||||||
|
Store = 1,
|
||||||
|
Resolve = 2,
|
||||||
|
StoreAndResolve = 3,
|
||||||
|
Discard = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PresentFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
AllowTearing = 1,
|
||||||
|
StrictlyTimedFrame = 2,
|
||||||
|
AllowDisplayLatencyWaitableObject = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class IndirectDrawArguments : uint32_t {
|
||||||
|
VertexCountPerInstance = 0,
|
||||||
|
InstanceCount = 4,
|
||||||
|
StartVertexLocation = 8,
|
||||||
|
StartInstanceLocation = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class IndirectDispatchArguments : uint32_t {
|
||||||
|
ThreadGroupCountX = 0,
|
||||||
|
ThreadGroupCountY = 4,
|
||||||
|
ThreadGroupCountZ = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class StencilOpDesc : uint8_t {
|
||||||
|
StencilFailOp,
|
||||||
|
StencilDepthFailOp,
|
||||||
|
StencilPassOp,
|
||||||
|
StencilFunc
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendStateFlag : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
IndependentBlendEnable = 1,
|
||||||
|
IndependentBlendEnable_8Targets = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DepthStencilStateFlag : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
DepthWrite = 1,
|
||||||
|
StencilWrite = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureAddressMode : uint8_t {
|
||||||
|
Wrap = 1,
|
||||||
|
Mirror = 2,
|
||||||
|
Clamp = 3,
|
||||||
|
Border = 4,
|
||||||
|
MirrorOnce = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FilterMode : uint8_t {
|
||||||
|
Point = 0,
|
||||||
|
Linear = 1,
|
||||||
|
Anisotropic = 2,
|
||||||
|
ComparisonPoint = 3,
|
||||||
|
ComparisonLinear = 4,
|
||||||
|
ComparisonAnisotropic = 5,
|
||||||
|
MinimumPoint = 7,
|
||||||
|
MinimumLinear = 8,
|
||||||
|
MinimumAnisotropic = 9,
|
||||||
|
MaximumPoint = 11,
|
||||||
|
MaximumLinear = 12,
|
||||||
|
MaximumAnisotropic = 13
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BorderColor : uint8_t {
|
||||||
|
TransparentBlack = 0,
|
||||||
|
OpaqueBlack = 1,
|
||||||
|
OpaqueWhite = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LogicOp : uint8_t {
|
||||||
|
Clear = 0,
|
||||||
|
Set = 1,
|
||||||
|
Copy = 2,
|
||||||
|
CopyInverted = 3,
|
||||||
|
Noop = 4,
|
||||||
|
Invert = 5,
|
||||||
|
And = 6,
|
||||||
|
Nand = 7,
|
||||||
|
Or = 8,
|
||||||
|
Nor = 9,
|
||||||
|
Xor = 10,
|
||||||
|
Equiv = 11,
|
||||||
|
AndReverse = 12,
|
||||||
|
AndInverted = 13,
|
||||||
|
OrReverse = 14,
|
||||||
|
OrInverted = 15
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ColorWriteMask : uint8_t {
|
||||||
|
Red = 1,
|
||||||
|
Green = 2,
|
||||||
|
Blue = 4,
|
||||||
|
Alpha = 8,
|
||||||
|
All = 15
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ColorWriteMask operator|(ColorWriteMask a, ColorWriteMask b) {
|
||||||
|
return static_cast<ColorWriteMask>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ResourceBarrierType : uint8_t {
|
||||||
|
Transition,
|
||||||
|
Aliasing,
|
||||||
|
UAV
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RootParameterType : uint8_t {
|
||||||
|
DescriptorTable,
|
||||||
|
Constants,
|
||||||
|
CBV,
|
||||||
|
SRV,
|
||||||
|
UAV
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ShaderRegisterType : uint8_t {
|
||||||
|
CBV,
|
||||||
|
SRV,
|
||||||
|
UAV,
|
||||||
|
Sampler
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RootSignatureVersion : uint8_t {
|
||||||
|
Version1,
|
||||||
|
Version1_0 = Version1,
|
||||||
|
Version1_1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ClearDepthStencilFlags : uint8_t {
|
||||||
|
Depth = 1,
|
||||||
|
Stencil = 2,
|
||||||
|
DepthAndStencil = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class QueryHeapFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Precision = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineStateFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
DebugName = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BufferUAVFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Raw = 1,
|
||||||
|
Append = 2,
|
||||||
|
Counter = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureLayout : uint8_t {
|
||||||
|
Unknown,
|
||||||
|
RowMajor,
|
||||||
|
_64KB_UNDEFINED_SWIZZLE,
|
||||||
|
Standard64KB
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CommandListFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
DisallowSetName = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FenceFlags : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Signal = 1,
|
||||||
|
Wait = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RHI
|
||||||
|
} // namespace XCEngine
|
||||||
BIN
tests/D3D12/Res/Image/earth_d.jpg
Normal file
BIN
tests/D3D12/Res/Image/earth_d.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
BIN
tests/D3D12/Res/Image/head.png
Normal file
BIN
tests/D3D12/Res/Image/head.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
tests/D3D12/Res/Model/Sphere.lhsm
Normal file
BIN
tests/D3D12/Res/Model/Sphere.lhsm
Normal file
Binary file not shown.
99
tests/D3D12/Res/Shader/gs.hlsl
Normal file
99
tests/D3D12/Res/Shader/gs.hlsl
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
struct VertexData{
|
||||||
|
float4 position:POSITION;
|
||||||
|
float4 texcoord:TEXCOORD0;
|
||||||
|
float4 normal:NORMAL;
|
||||||
|
float4 tangent:TANGENT;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSOut{
|
||||||
|
float4 position:SV_POSITION;
|
||||||
|
float4 normal:NORMAL;
|
||||||
|
float4 texcoord:TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float PI=3.141592;
|
||||||
|
cbuffer globalConstants:register(b0){
|
||||||
|
float4 misc;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2D T_DiffuseTexture:register(t0);
|
||||||
|
SamplerState samplerState:register(s0);
|
||||||
|
|
||||||
|
struct MaterialData{
|
||||||
|
float r;
|
||||||
|
};
|
||||||
|
StructuredBuffer<MaterialData> materialData:register(t0,space1);
|
||||||
|
cbuffer DefaultVertexCB:register(b1){
|
||||||
|
float4x4 ProjectionMatrix;
|
||||||
|
float4x4 ViewMatrix;
|
||||||
|
float4x4 ModelMatrix;
|
||||||
|
float4x4 IT_ModelMatrix;
|
||||||
|
float4x4 ReservedMemory[1020];
|
||||||
|
};
|
||||||
|
|
||||||
|
VSOut MainVS(VertexData inVertexData){
|
||||||
|
VSOut vo;
|
||||||
|
vo.normal=mul(IT_ModelMatrix,inVertexData.normal);
|
||||||
|
float4 positionWS=mul(ModelMatrix,inVertexData.position);
|
||||||
|
float4 positionVS=mul(ViewMatrix,positionWS);
|
||||||
|
vo.position=mul(ProjectionMatrix,positionVS);
|
||||||
|
//vo.position=float4(positionWS.xyz+vo.normal.xyz*sin(misc.x)*0.2f,1.0f);
|
||||||
|
vo.texcoord=inVertexData.texcoord;
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[maxvertexcount(4)]
|
||||||
|
void MainGS(triangle VSOut inPoint[3],uint inPrimitiveID:SV_PrimitiveID,
|
||||||
|
inout TriangleStream<VSOut> outTriangleStream){
|
||||||
|
outTriangleStream.Append(inPoint[0]);
|
||||||
|
outTriangleStream.Append(inPoint[1]);
|
||||||
|
outTriangleStream.Append(inPoint[2]);
|
||||||
|
/*VSOut vo;
|
||||||
|
float3 positionWS=inPoint[0].position.xyz;
|
||||||
|
float3 N=normalize(inPoint[0].normal.xyz);
|
||||||
|
vo.normal=float4(N,0.0f);
|
||||||
|
float3 helperVec=abs(N.y)>0.999?float3(0.0f,0.0f,1.0f):float3(0.0f,1.0f,0.0f);
|
||||||
|
float3 tangent=normalize(cross(N,helperVec));//u
|
||||||
|
float3 bitangent=normalize(cross(tangent,N));//v
|
||||||
|
float scale=materialData[inPrimitiveID].r;
|
||||||
|
|
||||||
|
|
||||||
|
float3 p0WS=positionWS-(bitangent*0.5f-tangent*0.5f)*scale;//left bottom
|
||||||
|
float4 p0VS=mul(ViewMatrix,float4(p0WS,1.0f));
|
||||||
|
vo.position=mul(ProjectionMatrix,p0VS);
|
||||||
|
vo.texcoord=float4(0.0f,1.0f,0.0f,0.0f);
|
||||||
|
outTriangleStream.Append(vo);
|
||||||
|
|
||||||
|
float3 p1WS=positionWS-(bitangent*0.5f+tangent*0.5f)*scale;//right bottom
|
||||||
|
float4 p1VS=mul(ViewMatrix,float4(p1WS,1.0f));
|
||||||
|
vo.position=mul(ProjectionMatrix,p1VS);
|
||||||
|
vo.texcoord=float4(1.0f,1.0f,0.0f,0.0f);
|
||||||
|
outTriangleStream.Append(vo);
|
||||||
|
|
||||||
|
float3 p2WS=positionWS+(bitangent*0.5f+tangent*0.5f)*scale;//left top
|
||||||
|
float4 p2VS=mul(ViewMatrix,float4(p2WS,1.0f));
|
||||||
|
vo.position=mul(ProjectionMatrix,p2VS);
|
||||||
|
vo.texcoord=float4(0.0f,0.0f,0.0f,0.0f);
|
||||||
|
outTriangleStream.Append(vo);
|
||||||
|
|
||||||
|
float3 p3WS=positionWS+(bitangent*0.5f-tangent*0.5f)*scale;//right top
|
||||||
|
float4 p3VS=mul(ViewMatrix,float4(p3WS,1.0f));
|
||||||
|
vo.position=mul(ProjectionMatrix,p3VS);
|
||||||
|
vo.texcoord=float4(1.0f,0.0f,0.0f,0.0f);
|
||||||
|
outTriangleStream.Append(vo);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(VSOut inPSInput):SV_TARGET{
|
||||||
|
float3 N=normalize(inPSInput.normal.xyz);
|
||||||
|
float3 bottomColor=float3(0.1f,0.4f,0.6f);
|
||||||
|
float3 topColor=float3(0.7f,0.7f,0.7f);
|
||||||
|
float theta=asin(N.y);//-PI/2 ~ PI/2
|
||||||
|
theta/=PI;//-0.5~0.5
|
||||||
|
theta+=0.5f;//0.0~1.0
|
||||||
|
float ambientColorIntensity=1.0;
|
||||||
|
float3 ambientColor=lerp(bottomColor,topColor,theta)*ambientColorIntensity;
|
||||||
|
float4 diffuseColor=T_DiffuseTexture.Sample(samplerState,inPSInput.texcoord.xy);
|
||||||
|
float3 surfaceColor=diffuseColor.rgb;
|
||||||
|
return float4(surfaceColor,1.0f);
|
||||||
|
}
|
||||||
65
tests/D3D12/Res/Shader/ndctriangle.hlsl
Normal file
65
tests/D3D12/Res/Shader/ndctriangle.hlsl
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
struct VertexData{
|
||||||
|
float4 position:POSITION;
|
||||||
|
float4 texcoord:TEXCOORD0;
|
||||||
|
float4 normal:NORMAL;
|
||||||
|
float4 tangent:TANGENT;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSOut{
|
||||||
|
float4 position:SV_POSITION;
|
||||||
|
float4 normal:NORMAL;
|
||||||
|
float4 texcoord:TEXCOORD0;
|
||||||
|
float4 positionWS:TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float PI=3.141592;
|
||||||
|
cbuffer globalConstants:register(b0){
|
||||||
|
float4 misc;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer DefaultVertexCB:register(b1){
|
||||||
|
float4x4 ProjectionMatrix;
|
||||||
|
float4x4 ViewMatrix;
|
||||||
|
float4x4 ModelMatrix;
|
||||||
|
float4x4 IT_ModelMatrix;
|
||||||
|
float4x4 ReservedMemory[1020];
|
||||||
|
};
|
||||||
|
|
||||||
|
VSOut MainVS(VertexData inVertexData){
|
||||||
|
VSOut vo;
|
||||||
|
vo.normal=mul(IT_ModelMatrix,inVertexData.normal);
|
||||||
|
float3 positionMS=inVertexData.position.xyz+vo.normal*sin(misc.x);
|
||||||
|
float4 positionWS=mul(ModelMatrix,float4(positionMS,1.0));
|
||||||
|
float4 positionVS=mul(ViewMatrix,positionWS);
|
||||||
|
vo.position=mul(ProjectionMatrix,positionVS);
|
||||||
|
vo.positionWS=positionWS;
|
||||||
|
vo.texcoord=inVertexData.texcoord;
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(VSOut inPSInput):SV_TARGET{
|
||||||
|
float3 N=normalize(inPSInput.normal.xyz);
|
||||||
|
float3 bottomColor=float3(0.1f,0.4f,0.6f);
|
||||||
|
float3 topColor=float3(0.7f,0.7f,0.7f);
|
||||||
|
float theta=asin(N.y);//-PI/2 ~ PI/2
|
||||||
|
theta/=PI;//-0.5~0.5
|
||||||
|
theta+=0.5f;//0.0~1.0
|
||||||
|
float ambientColorIntensity=0.2;
|
||||||
|
float3 ambientColor=lerp(bottomColor,topColor,theta)*ambientColorIntensity;
|
||||||
|
float3 L=normalize(float3(1.0f,1.0f,-1.0f));
|
||||||
|
|
||||||
|
float diffuseIntensity=max(0.0f,dot(N,L));
|
||||||
|
float3 diffuseLightColor=float3(0.1f,0.4f,0.6f);
|
||||||
|
float3 diffuseColor=diffuseLightColor*diffuseIntensity;
|
||||||
|
|
||||||
|
float3 specularColor=float3(0.0f,0.0f,0.0f);
|
||||||
|
if(diffuseIntensity>0.0f){
|
||||||
|
float3 cameraPositionWS=float3(0.0f,0.0f,0.0f);
|
||||||
|
float3 V=normalize(cameraPositionWS.xyz-inPSInput.positionWS.xyz);
|
||||||
|
float3 R=normalize(reflect(-L,N));
|
||||||
|
float specularIntensity=pow(max(0.0f,dot(V,R)),128.0f);
|
||||||
|
specularColor=float3(1.0f,1.0f,1.0f)*specularIntensity;
|
||||||
|
}
|
||||||
|
float3 surfaceColor=ambientColor+diffuseColor+specularColor;
|
||||||
|
return float4(surfaceColor,1.0f);
|
||||||
|
}
|
||||||
940
tests/D3D12/main.cpp
Normal file
940
tests/D3D12/main.cpp
Normal file
@@ -0,0 +1,940 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <d3d12.h>
|
||||||
|
#include <dxgi1_4.h>
|
||||||
|
#include <d3dcompiler.h>
|
||||||
|
#include <DirectXMath.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include "stbi/stb_image.h"
|
||||||
|
|
||||||
|
#pragma comment(lib,"d3d12.lib")
|
||||||
|
#pragma comment(lib,"dxgi.lib")
|
||||||
|
#pragma comment(lib,"d3dcompiler.lib")
|
||||||
|
#pragma comment(lib,"winmm.lib")
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// D3D12 核心全局对象 (最小渲染所需)
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12Device* gD3D12Device = nullptr;
|
||||||
|
ID3D12CommandQueue* gCommandQueue = nullptr;
|
||||||
|
IDXGISwapChain3* gSwapChain = nullptr;
|
||||||
|
|
||||||
|
// 渲染目标 (SwapChain的后台Buffer)
|
||||||
|
ID3D12Resource* gDSRT = nullptr; // 深度模板缓冲
|
||||||
|
ID3D12Resource* gColorRTs[2]; // 颜色缓冲 (双缓冲)
|
||||||
|
int gCurrentRTIndex = 0;
|
||||||
|
|
||||||
|
// 描述符堆
|
||||||
|
ID3D12DescriptorHeap* gSwapChainRTVHeap = nullptr; // RTV堆
|
||||||
|
ID3D12DescriptorHeap* gSwapChainDSVHeap = nullptr; // DSV堆
|
||||||
|
UINT gRTVDescriptorSize = 0;
|
||||||
|
UINT gDSVDescriptorSize = 0;
|
||||||
|
|
||||||
|
// 命令相关
|
||||||
|
ID3D12CommandAllocator* gCommandAllocator = nullptr;
|
||||||
|
ID3D12GraphicsCommandList* gCommandList = nullptr;
|
||||||
|
|
||||||
|
// 同步对象
|
||||||
|
ID3D12Fence* gFence = nullptr;
|
||||||
|
HANDLE gFenceEvent = nullptr;
|
||||||
|
UINT64 gFenceValue = 0;
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 工具函数前向声明
|
||||||
|
//=================================================================================
|
||||||
|
D3D12_RESOURCE_BARRIER InitResourceBarrier(
|
||||||
|
ID3D12Resource* inResource, D3D12_RESOURCE_STATES inPrevState,
|
||||||
|
D3D12_RESOURCE_STATES inNextState);
|
||||||
|
|
||||||
|
ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList,
|
||||||
|
void* inData, int inDataLen, D3D12_RESOURCE_STATES inFinalResourceState);
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 工具函数
|
||||||
|
//=================================================================================
|
||||||
|
float srandom() {
|
||||||
|
float number = float(rand()) / float(RAND_MAX);
|
||||||
|
number *= 2.0f;
|
||||||
|
number -= 1.0f;
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 数据结构定义
|
||||||
|
//=================================================================================
|
||||||
|
struct StaticMeshComponentVertexData {
|
||||||
|
float mPosition[4];
|
||||||
|
float mTexcoord[4];
|
||||||
|
float mNormal[4];
|
||||||
|
float mTangent[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubMesh {
|
||||||
|
ID3D12Resource* mIBO;
|
||||||
|
D3D12_INDEX_BUFFER_VIEW mIBView;
|
||||||
|
int mIndexCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 网格组件类 (StaticMeshComponent)
|
||||||
|
// 封装顶点缓冲(VBO)、索引缓冲(IBO)和渲染逻辑
|
||||||
|
//=================================================================================
|
||||||
|
class StaticMeshComponent {
|
||||||
|
public:
|
||||||
|
ID3D12Resource* mVBO;
|
||||||
|
D3D12_VERTEX_BUFFER_VIEW mVBOView;
|
||||||
|
StaticMeshComponentVertexData* mVertexData;
|
||||||
|
int mVertexCount;
|
||||||
|
std::unordered_map<std::string, SubMesh*> mSubMeshes;
|
||||||
|
|
||||||
|
void SetVertexCount(int inVertexCount) {
|
||||||
|
mVertexCount = inVertexCount;
|
||||||
|
mVertexData = new StaticMeshComponentVertexData[inVertexCount];
|
||||||
|
memset(mVertexData, 0, sizeof(StaticMeshComponentVertexData) * inVertexCount);
|
||||||
|
}
|
||||||
|
void SetVertexPosition(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||||
|
mVertexData[inIndex].mPosition[0] = inX;
|
||||||
|
mVertexData[inIndex].mPosition[1] = inY;
|
||||||
|
mVertexData[inIndex].mPosition[2] = inZ;
|
||||||
|
mVertexData[inIndex].mPosition[3] = inW;
|
||||||
|
}
|
||||||
|
void SetVertexTexcoord(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||||
|
mVertexData[inIndex].mTexcoord[0] = inX;
|
||||||
|
mVertexData[inIndex].mTexcoord[1] = inY;
|
||||||
|
mVertexData[inIndex].mTexcoord[2] = inZ;
|
||||||
|
mVertexData[inIndex].mTexcoord[3] = inW;
|
||||||
|
}
|
||||||
|
void SetVertexNormal(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||||
|
mVertexData[inIndex].mNormal[0] = inX;
|
||||||
|
mVertexData[inIndex].mNormal[1] = inY;
|
||||||
|
mVertexData[inIndex].mNormal[2] = inZ;
|
||||||
|
mVertexData[inIndex].mNormal[3] = inW;
|
||||||
|
}
|
||||||
|
void SetVertexTangent(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||||
|
mVertexData[inIndex].mTangent[0] = inX;
|
||||||
|
mVertexData[inIndex].mTangent[1] = inY;
|
||||||
|
mVertexData[inIndex].mTangent[2] = inZ;
|
||||||
|
mVertexData[inIndex].mTangent[3] = inW;
|
||||||
|
}
|
||||||
|
void InitFromFile(ID3D12GraphicsCommandList* inCommandList, const char* inFilePath) {
|
||||||
|
FILE* pFile = nullptr;
|
||||||
|
errno_t err = fopen_s(&pFile, inFilePath, "rb");
|
||||||
|
if (err == 0) {
|
||||||
|
int temp = 0;
|
||||||
|
fread(&temp, 4, 1, pFile);
|
||||||
|
mVertexCount = temp;
|
||||||
|
mVertexData = new StaticMeshComponentVertexData[mVertexCount];
|
||||||
|
fread(mVertexData, 1, sizeof(StaticMeshComponentVertexData) * mVertexCount, pFile);
|
||||||
|
mVBO = CreateBufferObject(inCommandList, mVertexData,
|
||||||
|
sizeof(StaticMeshComponentVertexData) * mVertexCount,
|
||||||
|
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
|
||||||
|
mVBOView.BufferLocation = mVBO->GetGPUVirtualAddress();
|
||||||
|
mVBOView.SizeInBytes = sizeof(StaticMeshComponentVertexData) * mVertexCount;
|
||||||
|
mVBOView.StrideInBytes = sizeof(StaticMeshComponentVertexData);
|
||||||
|
|
||||||
|
while (!feof(pFile)) {
|
||||||
|
fread(&temp, 4, 1, pFile);
|
||||||
|
if (feof(pFile)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char name[256] = { 0 };
|
||||||
|
fread(name, 1, temp, pFile);
|
||||||
|
fread(&temp, 4, 1, pFile);
|
||||||
|
SubMesh* submesh = new SubMesh;
|
||||||
|
submesh->mIndexCount = temp;
|
||||||
|
unsigned int* indexes = new unsigned int[temp];
|
||||||
|
fread(indexes, 1, sizeof(unsigned int) * temp, pFile);
|
||||||
|
submesh->mIBO = CreateBufferObject(inCommandList, indexes,
|
||||||
|
sizeof(unsigned int) * temp,
|
||||||
|
D3D12_RESOURCE_STATE_INDEX_BUFFER);
|
||||||
|
|
||||||
|
submesh->mIBView.BufferLocation = submesh->mIBO->GetGPUVirtualAddress();
|
||||||
|
submesh->mIBView.SizeInBytes = sizeof(unsigned int) * temp;
|
||||||
|
submesh->mIBView.Format = DXGI_FORMAT_R32_UINT;
|
||||||
|
mSubMeshes.insert(std::pair<std::string, SubMesh*>(name, submesh));
|
||||||
|
delete[] indexes;
|
||||||
|
}
|
||||||
|
fclose(pFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Render(ID3D12GraphicsCommandList* inCommandList) {
|
||||||
|
D3D12_VERTEX_BUFFER_VIEW vbos[] = {
|
||||||
|
mVBOView
|
||||||
|
};
|
||||||
|
inCommandList->IASetVertexBuffers(0, 1, vbos);
|
||||||
|
if (mSubMeshes.empty()) {
|
||||||
|
inCommandList->DrawInstanced(mVertexCount, 1, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto iter = mSubMeshes.begin();
|
||||||
|
iter != mSubMeshes.end(); iter++) {
|
||||||
|
inCommandList->IASetIndexBuffer(&iter->second->mIBView);
|
||||||
|
inCommandList->DrawIndexedInstanced(iter->second->mIndexCount, 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// ResourceBarrier 工具函数
|
||||||
|
// 用于资源状态转换 (例如: PRESENT → RENDER_TARGET)
|
||||||
|
//=================================================================================
|
||||||
|
D3D12_RESOURCE_BARRIER InitResourceBarrier(
|
||||||
|
ID3D12Resource* inResource, D3D12_RESOURCE_STATES inPrevState,
|
||||||
|
D3D12_RESOURCE_STATES inNextState) {
|
||||||
|
D3D12_RESOURCE_BARRIER d3d12ResourceBarrier;
|
||||||
|
memset(&d3d12ResourceBarrier, 0, sizeof(d3d12ResourceBarrier));
|
||||||
|
d3d12ResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||||
|
d3d12ResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||||
|
d3d12ResourceBarrier.Transition.pResource = inResource;
|
||||||
|
d3d12ResourceBarrier.Transition.StateBefore = inPrevState;
|
||||||
|
d3d12ResourceBarrier.Transition.StateAfter = inNextState;
|
||||||
|
d3d12ResourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||||
|
return d3d12ResourceBarrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 根签名初始化 (RootSignature)
|
||||||
|
// 定义GPU资源绑定规则: CBV(常量缓冲) / SRV(着色器资源) / DescriptorTable
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12RootSignature* InitRootSignature() {
|
||||||
|
D3D12_ROOT_PARAMETER rootParameters[4];
|
||||||
|
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||||
|
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||||
|
rootParameters[1].Constants.RegisterSpace = 0;
|
||||||
|
rootParameters[1].Constants.ShaderRegister = 0;
|
||||||
|
rootParameters[1].Constants.Num32BitValues = 4;
|
||||||
|
|
||||||
|
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||||
|
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
rootParameters[0].Descriptor.RegisterSpace = 0;
|
||||||
|
rootParameters[0].Descriptor.ShaderRegister = 1;
|
||||||
|
|
||||||
|
D3D12_DESCRIPTOR_RANGE descriptorRange[1];
|
||||||
|
descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||||
|
descriptorRange[0].RegisterSpace = 0;
|
||||||
|
descriptorRange[0].BaseShaderRegister = 0;
|
||||||
|
descriptorRange[0].NumDescriptors = 1;
|
||||||
|
descriptorRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||||
|
|
||||||
|
rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||||
|
rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||||
|
rootParameters[2].DescriptorTable.pDescriptorRanges = descriptorRange;
|
||||||
|
rootParameters[2].DescriptorTable.NumDescriptorRanges = _countof(descriptorRange);
|
||||||
|
|
||||||
|
rootParameters[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
||||||
|
rootParameters[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
rootParameters[3].Descriptor.RegisterSpace = 1;
|
||||||
|
rootParameters[3].Descriptor.ShaderRegister = 0;
|
||||||
|
|
||||||
|
D3D12_STATIC_SAMPLER_DESC samplerDesc[1];
|
||||||
|
memset(samplerDesc, 0, sizeof(D3D12_STATIC_SAMPLER_DESC) * _countof(samplerDesc));
|
||||||
|
samplerDesc[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||||
|
samplerDesc[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
|
samplerDesc[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
|
samplerDesc[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
|
samplerDesc[0].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
||||||
|
samplerDesc[0].MaxLOD = D3D12_FLOAT32_MAX;
|
||||||
|
samplerDesc[0].RegisterSpace = 0;
|
||||||
|
samplerDesc[0].ShaderRegister = 0;
|
||||||
|
samplerDesc[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||||
|
|
||||||
|
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
||||||
|
rootSignatureDesc.NumParameters = _countof(rootParameters);
|
||||||
|
rootSignatureDesc.pParameters = rootParameters;
|
||||||
|
rootSignatureDesc.NumStaticSamplers = _countof(samplerDesc);
|
||||||
|
rootSignatureDesc.pStaticSamplers = samplerDesc;
|
||||||
|
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||||
|
|
||||||
|
ID3DBlob* signature;
|
||||||
|
HRESULT hResult = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr);
|
||||||
|
ID3D12RootSignature* d3d12RootSignature;
|
||||||
|
gD3D12Device->CreateRootSignature(
|
||||||
|
0, signature->GetBufferPointer(), signature->GetBufferSize(),
|
||||||
|
IID_PPV_ARGS(&d3d12RootSignature));
|
||||||
|
|
||||||
|
return d3d12RootSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 着色器加载函数
|
||||||
|
// 从.hlsl文件编译着色器 (VS/GS/PS)
|
||||||
|
//=================================================================================
|
||||||
|
void CreateShaderFromFile(
|
||||||
|
LPCTSTR inShaderFilePath,
|
||||||
|
const char* inMainFunctionName,
|
||||||
|
const char* inTarget,
|
||||||
|
D3D12_SHADER_BYTECODE* inShader) {
|
||||||
|
ID3DBlob* shaderBuffer = nullptr;
|
||||||
|
ID3DBlob* errorBuffer = nullptr;
|
||||||
|
HRESULT hResult = D3DCompileFromFile(inShaderFilePath, nullptr, nullptr,
|
||||||
|
inMainFunctionName, inTarget, D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||||
|
0, &shaderBuffer, &errorBuffer);
|
||||||
|
if (FAILED(hResult)) {
|
||||||
|
char szLog[1024] = { 0 };
|
||||||
|
strcpy_s(szLog, (char*)errorBuffer->GetBufferPointer());
|
||||||
|
printf("CreateShaderFromFile error : [%s][%s]:[%s]\n", inMainFunctionName, inTarget, szLog);
|
||||||
|
errorBuffer->Release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inShader->pShaderBytecode = shaderBuffer->GetBufferPointer();
|
||||||
|
inShader->BytecodeLength = shaderBuffer->GetBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 常量缓冲 (Constant Buffer) 创建与更新
|
||||||
|
// UPLOAD堆: CPU可写, GPU可读
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12Resource* CreateConstantBufferObject(int inDataLen) {
|
||||||
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||||
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
|
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||||
|
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
d3d12ResourceDesc.Alignment = 0;
|
||||||
|
d3d12ResourceDesc.Width = inDataLen;
|
||||||
|
d3d12ResourceDesc.Height = 1;
|
||||||
|
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||||
|
d3d12ResourceDesc.MipLevels = 1;
|
||||||
|
d3d12ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||||
|
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
ID3D12Resource* bufferObject = nullptr;
|
||||||
|
gD3D12Device->CreateCommittedResource(
|
||||||
|
&d3dHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12ResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&bufferObject)
|
||||||
|
);
|
||||||
|
return bufferObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 更新常量缓冲数据
|
||||||
|
//=================================================================================
|
||||||
|
void UpdateConstantBuffer(ID3D12Resource* inCB, void* inData, int inDataLen) {
|
||||||
|
D3D12_RANGE d3d12Range = { 0 };
|
||||||
|
unsigned char* pBuffer = nullptr;
|
||||||
|
inCB->Map(0, &d3d12Range, (void**)&pBuffer);
|
||||||
|
memcpy(pBuffer, inData, inDataLen);
|
||||||
|
inCB->Unmap(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// GPU Buffer创建 (顶点/索引缓冲)
|
||||||
|
// DEFAULT堆 → 通过Upload堆中转数据 → 状态转换
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList,
|
||||||
|
void* inData, int inDataLen, D3D12_RESOURCE_STATES inFinalResourceState) {
|
||||||
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||||
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||||
|
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
d3d12ResourceDesc.Alignment = 0;
|
||||||
|
d3d12ResourceDesc.Width = inDataLen;
|
||||||
|
d3d12ResourceDesc.Height = 1;
|
||||||
|
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||||
|
d3d12ResourceDesc.MipLevels = 1;
|
||||||
|
d3d12ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||||
|
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
ID3D12Resource* bufferObject = nullptr;
|
||||||
|
gD3D12Device->CreateCommittedResource(
|
||||||
|
&d3dHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12ResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&bufferObject)
|
||||||
|
);
|
||||||
|
d3d12ResourceDesc = bufferObject->GetDesc();
|
||||||
|
UINT64 memorySizeUsed = 0;
|
||||||
|
UINT64 rowSizeInBytes = 0;
|
||||||
|
UINT rowUsed = 0;
|
||||||
|
D3D12_PLACED_SUBRESOURCE_FOOTPRINT subresourceFootprint;
|
||||||
|
gD3D12Device->GetCopyableFootprints(&d3d12ResourceDesc, 0, 1, 0,
|
||||||
|
&subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed);
|
||||||
|
|
||||||
|
ID3D12Resource* tempBufferObject = nullptr;
|
||||||
|
d3dHeapProperties = {};
|
||||||
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
|
gD3D12Device->CreateCommittedResource(
|
||||||
|
&d3dHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12ResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&tempBufferObject)
|
||||||
|
);
|
||||||
|
|
||||||
|
BYTE* pData;
|
||||||
|
tempBufferObject->Map(0, nullptr, reinterpret_cast<void**>(&pData));
|
||||||
|
BYTE* pDstTempBuffer = reinterpret_cast<BYTE*>(pData + subresourceFootprint.Offset);
|
||||||
|
const BYTE* pSrcData = reinterpret_cast<BYTE*>(inData);
|
||||||
|
for (UINT i = 0; i < rowUsed; i++) {
|
||||||
|
memcpy(pDstTempBuffer + subresourceFootprint.Footprint.RowPitch * i, pSrcData + rowSizeInBytes * i, rowSizeInBytes);
|
||||||
|
}
|
||||||
|
tempBufferObject->Unmap(0, nullptr);
|
||||||
|
inCommandList->CopyBufferRegion(bufferObject, 0, tempBufferObject, 0, subresourceFootprint.Footprint.Width);
|
||||||
|
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(bufferObject, D3D12_RESOURCE_STATE_COPY_DEST, inFinalResourceState);
|
||||||
|
inCommandList->ResourceBarrier(1, &barrier);
|
||||||
|
return bufferObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 2D纹理创建
|
||||||
|
// DEFAULT堆 → 通过Upload堆中转数据 → CopyTextureRegion → 状态转换
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12Resource* CreateTexture2D(ID3D12GraphicsCommandList* inCommandList,
|
||||||
|
const void* inPixelData, int inDataSizeInBytes, int inWidth, int inHeight,
|
||||||
|
DXGI_FORMAT inFormat) {
|
||||||
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||||
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||||
|
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||||
|
d3d12ResourceDesc.Alignment = 0;
|
||||||
|
d3d12ResourceDesc.Width = inWidth;
|
||||||
|
d3d12ResourceDesc.Height = inHeight;
|
||||||
|
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||||
|
d3d12ResourceDesc.MipLevels = 1;
|
||||||
|
d3d12ResourceDesc.Format = inFormat;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||||
|
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||||
|
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
ID3D12Resource* texture = nullptr;
|
||||||
|
gD3D12Device->CreateCommittedResource(&d3dHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12ResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&texture)
|
||||||
|
);
|
||||||
|
d3d12ResourceDesc = texture->GetDesc();
|
||||||
|
UINT64 memorySizeUsed = 0;
|
||||||
|
UINT64 rowSizeInBytes = 0;
|
||||||
|
UINT rowUsed = 0;
|
||||||
|
D3D12_PLACED_SUBRESOURCE_FOOTPRINT subresourceFootprint;
|
||||||
|
gD3D12Device->GetCopyableFootprints(&d3d12ResourceDesc, 0, 1, 0,
|
||||||
|
&subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed);
|
||||||
|
|
||||||
|
ID3D12Resource* tempBufferObject = nullptr;
|
||||||
|
D3D12_HEAP_PROPERTIES d3dTempHeapProperties = {};
|
||||||
|
d3dTempHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC d3d12TempResourceDesc = {};
|
||||||
|
d3d12TempResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
d3d12TempResourceDesc.Alignment = 0;
|
||||||
|
d3d12TempResourceDesc.Width = memorySizeUsed;
|
||||||
|
d3d12TempResourceDesc.Height = 1;
|
||||||
|
d3d12TempResourceDesc.DepthOrArraySize = 1;
|
||||||
|
d3d12TempResourceDesc.MipLevels = 1;
|
||||||
|
d3d12TempResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
d3d12TempResourceDesc.SampleDesc.Count = 1;
|
||||||
|
d3d12TempResourceDesc.SampleDesc.Quality = 0;
|
||||||
|
d3d12TempResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
d3d12TempResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
gD3D12Device->CreateCommittedResource(
|
||||||
|
&d3dTempHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12TempResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&tempBufferObject)
|
||||||
|
);
|
||||||
|
BYTE* pData;
|
||||||
|
tempBufferObject->Map(0, nullptr, reinterpret_cast<void**>(&pData));
|
||||||
|
BYTE* pDstTempBuffer = reinterpret_cast<BYTE*>(pData + subresourceFootprint.Offset);
|
||||||
|
const BYTE* pSrcData = reinterpret_cast<const BYTE*>(inPixelData);
|
||||||
|
for (UINT i = 0; i < rowUsed; i++) {
|
||||||
|
memcpy(pDstTempBuffer + subresourceFootprint.Footprint.RowPitch * i, pSrcData + rowSizeInBytes * i, rowSizeInBytes);
|
||||||
|
}
|
||||||
|
tempBufferObject->Unmap(0, nullptr);
|
||||||
|
D3D12_TEXTURE_COPY_LOCATION dst = {};
|
||||||
|
dst.pResource = texture;
|
||||||
|
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
|
dst.SubresourceIndex = 0;
|
||||||
|
|
||||||
|
D3D12_TEXTURE_COPY_LOCATION src = {};
|
||||||
|
src.pResource = tempBufferObject;
|
||||||
|
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||||
|
src.PlacedFootprint = subresourceFootprint;
|
||||||
|
inCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||||
|
|
||||||
|
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(texture,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
|
inCommandList->ResourceBarrier(1, &barrier);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 渲染管线状态对象 (PSO)
|
||||||
|
// 包含: InputLayout / VS/GS/PS / Rasterizer / DepthStencil / Blend
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12PipelineState* CreatePSO(ID3D12RootSignature* inID3D12RootSignature,
|
||||||
|
D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader,
|
||||||
|
D3D12_SHADER_BYTECODE inGSShader) {
|
||||||
|
D3D12_INPUT_ELEMENT_DESC vertexDataElementDesc[] = {
|
||||||
|
{"POSITION",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||||
|
{"TEXCOORD",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 4,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||||
|
{"NORMAL",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 8,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||||
|
{"TANGENT",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 12,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}
|
||||||
|
};
|
||||||
|
D3D12_INPUT_LAYOUT_DESC vertexDataLayoutDesc = {};
|
||||||
|
vertexDataLayoutDesc.NumElements = 4;
|
||||||
|
vertexDataLayoutDesc.pInputElementDescs = vertexDataElementDesc;
|
||||||
|
|
||||||
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||||
|
psoDesc.pRootSignature = inID3D12RootSignature;
|
||||||
|
psoDesc.VS = inVertexShader;
|
||||||
|
psoDesc.GS = inGSShader;
|
||||||
|
psoDesc.PS = inPixelShader;
|
||||||
|
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
psoDesc.SampleDesc.Count = 1;
|
||||||
|
psoDesc.SampleDesc.Quality = 0;
|
||||||
|
psoDesc.SampleMask = 0xffffffff;
|
||||||
|
psoDesc.InputLayout = vertexDataLayoutDesc;
|
||||||
|
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||||
|
|
||||||
|
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||||
|
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
||||||
|
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
||||||
|
|
||||||
|
psoDesc.DepthStencilState.DepthEnable = true;
|
||||||
|
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||||
|
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||||
|
|
||||||
|
psoDesc.BlendState = { 0 };
|
||||||
|
D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc = {
|
||||||
|
FALSE,FALSE,
|
||||||
|
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
||||||
|
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
||||||
|
D3D12_LOGIC_OP_NOOP,
|
||||||
|
D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||||
|
};
|
||||||
|
for (int i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
|
||||||
|
psoDesc.BlendState.RenderTarget[i] = rtBlendDesc;
|
||||||
|
psoDesc.NumRenderTargets = 1;
|
||||||
|
ID3D12PipelineState* d3d12PSO = nullptr;
|
||||||
|
|
||||||
|
HRESULT hResult = gD3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&d3d12PSO));
|
||||||
|
if (FAILED(hResult)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return d3d12PSO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// D3D12 初始化核心函数 (InitD3D12)
|
||||||
|
// 最小渲染系统初始化流程:
|
||||||
|
// 1. 启用Debug层 (可选, _DEBUG)
|
||||||
|
// 2. 创建IDXGIFactory4
|
||||||
|
// 3. 枚举Adapter, 创建ID3D12Device
|
||||||
|
// 4. 创建CommandQueue (命令队列)
|
||||||
|
// 5. 创建SwapChain (交换链)
|
||||||
|
// 6. 创建DepthStencilBuffer (深度缓冲)
|
||||||
|
// 7. 创建RTV/DSV描述符堆
|
||||||
|
// 8. 创建RenderTargetView / DepthStencilView
|
||||||
|
// 9. 创建CommandAllocator / CommandList
|
||||||
|
// 10. 创建Fence (同步)
|
||||||
|
//=================================================================================
|
||||||
|
bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
||||||
|
HRESULT hResult;
|
||||||
|
UINT dxgiFactoryFlags = 0;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
{
|
||||||
|
ID3D12Debug* debugController = nullptr;
|
||||||
|
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||||
|
debugController->EnableDebugLayer();
|
||||||
|
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
IDXGIFactory4* dxgiFactory;
|
||||||
|
hResult = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&dxgiFactory));
|
||||||
|
if (FAILED(hResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IDXGIAdapter1* adapter;
|
||||||
|
int adapterIndex = 0;
|
||||||
|
bool adapterFound = false;
|
||||||
|
while (dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
||||||
|
DXGI_ADAPTER_DESC1 desc;
|
||||||
|
adapter->GetDesc1(&desc);
|
||||||
|
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hResult = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
|
||||||
|
if (SUCCEEDED(hResult)) {
|
||||||
|
adapterFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
adapterIndex++;
|
||||||
|
}
|
||||||
|
if (false == adapterFound) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
hResult = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gD3D12Device));
|
||||||
|
if (FAILED(hResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
D3D12_COMMAND_QUEUE_DESC d3d12CommandQueueDesc = {};
|
||||||
|
hResult = gD3D12Device->CreateCommandQueue(&d3d12CommandQueueDesc, IID_PPV_ARGS(&gCommandQueue));
|
||||||
|
if (FAILED(hResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
||||||
|
swapChainDesc.BufferCount = 2;
|
||||||
|
swapChainDesc.BufferDesc = {};
|
||||||
|
swapChainDesc.BufferDesc.Width = inWidth;
|
||||||
|
swapChainDesc.BufferDesc.Height = inHeight;
|
||||||
|
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
swapChainDesc.OutputWindow = inHWND;
|
||||||
|
swapChainDesc.SampleDesc.Count = 1;
|
||||||
|
swapChainDesc.Windowed = true;
|
||||||
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
|
||||||
|
IDXGISwapChain* swapChain = nullptr;
|
||||||
|
dxgiFactory->CreateSwapChain(gCommandQueue, &swapChainDesc, &swapChain);
|
||||||
|
gSwapChain = static_cast<IDXGISwapChain3*>(swapChain);
|
||||||
|
|
||||||
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||||
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||||
|
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||||
|
d3d12ResourceDesc.Alignment = 0;
|
||||||
|
d3d12ResourceDesc.Width = inWidth;
|
||||||
|
d3d12ResourceDesc.Height = inHeight;
|
||||||
|
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||||
|
d3d12ResourceDesc.MipLevels = 1;
|
||||||
|
d3d12ResourceDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||||
|
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||||
|
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||||
|
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
|
|
||||||
|
D3D12_CLEAR_VALUE dsClearValue = {};
|
||||||
|
dsClearValue.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
dsClearValue.DepthStencil.Depth = 1.0f;
|
||||||
|
dsClearValue.DepthStencil.Stencil = 0;
|
||||||
|
|
||||||
|
gD3D12Device->CreateCommittedResource(&d3dHeapProperties,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&d3d12ResourceDesc,
|
||||||
|
D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||||
|
&dsClearValue,
|
||||||
|
IID_PPV_ARGS(&gDSRT)
|
||||||
|
);
|
||||||
|
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescRTV = {};
|
||||||
|
d3dDescriptorHeapDescRTV.NumDescriptors = 2;
|
||||||
|
d3dDescriptorHeapDescRTV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||||
|
gD3D12Device->CreateDescriptorHeap(&d3dDescriptorHeapDescRTV, IID_PPV_ARGS(&gSwapChainRTVHeap));
|
||||||
|
gRTVDescriptorSize = gD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||||
|
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescDSV = {};
|
||||||
|
d3dDescriptorHeapDescDSV.NumDescriptors = 1;
|
||||||
|
d3dDescriptorHeapDescDSV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
||||||
|
gD3D12Device->CreateDescriptorHeap(&d3dDescriptorHeapDescDSV, IID_PPV_ARGS(&gSwapChainDSVHeap));
|
||||||
|
gDSVDescriptorSize = gD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
||||||
|
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvHeapStart = gSwapChainRTVHeap->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
gSwapChain->GetBuffer(i, IID_PPV_ARGS(&gColorRTs[i]));
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvPointer;
|
||||||
|
rtvPointer.ptr = rtvHeapStart.ptr + i * gRTVDescriptorSize;
|
||||||
|
gD3D12Device->CreateRenderTargetView(gColorRTs[i], nullptr, rtvPointer);
|
||||||
|
}
|
||||||
|
D3D12_DEPTH_STENCIL_VIEW_DESC d3dDSViewDesc = {};
|
||||||
|
d3dDSViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
d3dDSViewDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
|
gD3D12Device->CreateDepthStencilView(gDSRT, &d3dDSViewDesc, gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart());
|
||||||
|
|
||||||
|
gD3D12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gCommandAllocator));
|
||||||
|
gD3D12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gCommandAllocator, nullptr, IID_PPV_ARGS(&gCommandList));
|
||||||
|
|
||||||
|
gD3D12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gFence));
|
||||||
|
gFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 命令相关辅助函数
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12CommandAllocator* GetCommandAllocator() {
|
||||||
|
return gCommandAllocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList* GetCommandList() {
|
||||||
|
return gCommandList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForCompletionOfCommandList() {
|
||||||
|
if (gFence->GetCompletedValue() < gFenceValue) {
|
||||||
|
gFence->SetEventOnCompletion(gFenceValue, gFenceEvent);
|
||||||
|
WaitForSingleObject(gFenceEvent, INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 命令列表结束提交
|
||||||
|
// 关闭CommandList → ExecuteCommandLists → Signal Fence
|
||||||
|
//=================================================================================
|
||||||
|
void EndCommandList() {
|
||||||
|
gCommandList->Close();
|
||||||
|
ID3D12CommandList* ppCommandLists[] = { gCommandList };
|
||||||
|
gCommandQueue->ExecuteCommandLists(1, ppCommandLists);
|
||||||
|
gFenceValue += 1;
|
||||||
|
gCommandQueue->Signal(gFence, gFenceValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 开始渲染到SwapChain
|
||||||
|
// 1. 获取当前BackBuffer索引
|
||||||
|
// 2. 状态转换: PRESENT → RENDER_TARGET
|
||||||
|
// 3. 设置RenderTargets (Color + Depth)
|
||||||
|
// 4. 设置Viewport/Scissor
|
||||||
|
// 5. Clear Color/Depth
|
||||||
|
//=================================================================================
|
||||||
|
void BeginRenderToSwapChain(ID3D12GraphicsCommandList* inCommandList) {
|
||||||
|
gCurrentRTIndex = gSwapChain->GetCurrentBackBufferIndex();
|
||||||
|
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(gColorRTs[gCurrentRTIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
inCommandList->ResourceBarrier(1, &barrier);
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE colorRT, dsv;
|
||||||
|
dsv.ptr = gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||||
|
colorRT.ptr = gSwapChainRTVHeap->GetCPUDescriptorHandleForHeapStart().ptr + gCurrentRTIndex * gRTVDescriptorSize;
|
||||||
|
inCommandList->OMSetRenderTargets(1, &colorRT, FALSE, &dsv);
|
||||||
|
D3D12_VIEWPORT viewport = { 0.0f,0.0f,1280.0f,720.0f };
|
||||||
|
D3D12_RECT scissorRect = { 0,0,1280,720 };
|
||||||
|
inCommandList->RSSetViewports(1, &viewport);
|
||||||
|
inCommandList->RSSetScissorRects(1, &scissorRect);
|
||||||
|
const float clearColor[] = { 0.0f,0.0f,0.0f,1.0f };
|
||||||
|
inCommandList->ClearRenderTargetView(colorRT, clearColor, 0, nullptr);
|
||||||
|
inCommandList->ClearDepthStencilView(dsv, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 结束渲染到SwapChain
|
||||||
|
// 状态转换: RENDER_TARGET → PRESENT
|
||||||
|
//=================================================================================
|
||||||
|
void EndRenderToSwapChain(ID3D12GraphicsCommandList* inCommandList) {
|
||||||
|
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(gColorRTs[gCurrentRTIndex], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
|
||||||
|
inCommandList->ResourceBarrier(1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 交换缓冲区 (显示渲染结果)
|
||||||
|
//=================================================================================
|
||||||
|
void SwapD3D12Buffers() {
|
||||||
|
gSwapChain->Present(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 获取D3D12设备
|
||||||
|
//=================================================================================
|
||||||
|
ID3D12Device* GetD3DDevice() {
|
||||||
|
return gD3D12Device;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// Win32 窗口相关
|
||||||
|
//=================================================================================
|
||||||
|
LPCTSTR gWindowClassName = L"BattleFire";
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 窗口消息回调函数
|
||||||
|
//=================================================================================
|
||||||
|
LRESULT CALLBACK WindowProc(HWND inHWND, UINT inMSG, WPARAM inWParam, LPARAM inLParam) {
|
||||||
|
switch (inMSG) {
|
||||||
|
case WM_CLOSE:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return DefWindowProc(inHWND, inMSG, inWParam, inLParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
// 主入口函数 WinMain
|
||||||
|
// 程序入口点
|
||||||
|
//=================================================================================
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int inShowCmd) {
|
||||||
|
WNDCLASSEX wndClassEx;
|
||||||
|
wndClassEx.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wndClassEx.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wndClassEx.cbClsExtra = NULL;
|
||||||
|
wndClassEx.cbWndExtra = NULL;
|
||||||
|
wndClassEx.hInstance = hInstance;
|
||||||
|
wndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wndClassEx.hbrBackground = NULL;
|
||||||
|
wndClassEx.lpszMenuName = NULL;
|
||||||
|
wndClassEx.lpszClassName = gWindowClassName;
|
||||||
|
wndClassEx.lpfnWndProc = WindowProc;
|
||||||
|
if (!RegisterClassEx(&wndClassEx)) {
|
||||||
|
MessageBox(NULL, L"Register Class Failed!", L"Error", MB_OK | MB_ICONERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewportWidth = 1280;
|
||||||
|
int viewportHeight = 720;
|
||||||
|
RECT rect;
|
||||||
|
rect.left = 0;
|
||||||
|
rect.top = 0;
|
||||||
|
rect.right = viewportWidth;
|
||||||
|
rect.bottom = viewportHeight;
|
||||||
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
|
int windowWidth = rect.right - rect.left;
|
||||||
|
int windowHeight = rect.bottom - rect.top;
|
||||||
|
HWND hwnd = CreateWindowEx(NULL,
|
||||||
|
gWindowClassName,
|
||||||
|
L"My Render Window",
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
windowWidth, windowHeight,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
if (!hwnd) {
|
||||||
|
MessageBox(NULL, L"Create Window Failed!", L"Error", MB_OK | MB_ICONERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitD3D12(hwnd, 1280, 720);
|
||||||
|
ID3D12GraphicsCommandList* commandList = GetCommandList();
|
||||||
|
ID3D12CommandAllocator* commandAllocator = GetCommandAllocator();
|
||||||
|
StaticMeshComponent staticMeshComponent;
|
||||||
|
staticMeshComponent.InitFromFile(commandList, "Res/Model/Sphere.lhsm");
|
||||||
|
|
||||||
|
ID3D12RootSignature* rootSignature = InitRootSignature();
|
||||||
|
D3D12_SHADER_BYTECODE vs, gs, ps;
|
||||||
|
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainVS", "vs_5_1", &vs);
|
||||||
|
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainGS", "gs_5_1", &gs);
|
||||||
|
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainPS", "ps_5_1", &ps);
|
||||||
|
ID3D12PipelineState* pso = CreatePSO(rootSignature, vs, ps, gs);
|
||||||
|
|
||||||
|
ID3D12Resource* cb = CreateConstantBufferObject(65536);
|
||||||
|
DirectX::XMMATRIX projectionMatrix = DirectX::XMMatrixPerspectiveFovLH(
|
||||||
|
(45.0f * 3.141592f) / 180.0f, 1280.0f / 720.0f, 0.1f, 1000.0f);
|
||||||
|
DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixIdentity();
|
||||||
|
DirectX::XMMATRIX modelMatrix = DirectX::XMMatrixTranslation(0.0f, 0.0f, 5.0f);
|
||||||
|
DirectX::XMFLOAT4X4 tempMatrix;
|
||||||
|
float matrices[64];
|
||||||
|
|
||||||
|
DirectX::XMStoreFloat4x4(&tempMatrix, projectionMatrix);
|
||||||
|
memcpy(matrices, &tempMatrix, sizeof(float) * 16);
|
||||||
|
DirectX::XMStoreFloat4x4(&tempMatrix, viewMatrix);
|
||||||
|
memcpy(matrices + 16, &tempMatrix, sizeof(float) * 16);
|
||||||
|
DirectX::XMStoreFloat4x4(&tempMatrix, modelMatrix);
|
||||||
|
memcpy(matrices + 32, &tempMatrix, sizeof(float) * 16);
|
||||||
|
DirectX::XMVECTOR determinant;
|
||||||
|
DirectX::XMMATRIX inverseModelMatrix = DirectX::XMMatrixInverse(&determinant, modelMatrix);
|
||||||
|
if (DirectX::XMVectorGetX(determinant) != 0.0f) {
|
||||||
|
DirectX::XMMATRIX normalMatrix = DirectX::XMMatrixTranspose(inverseModelMatrix);
|
||||||
|
DirectX::XMStoreFloat4x4(&tempMatrix, modelMatrix);
|
||||||
|
memcpy(matrices + 48, &tempMatrix, sizeof(float) * 16);
|
||||||
|
}
|
||||||
|
UpdateConstantBuffer(cb, matrices, sizeof(float) * 64);
|
||||||
|
|
||||||
|
ID3D12Resource* sb = CreateConstantBufferObject(65536);
|
||||||
|
struct MaterialData {
|
||||||
|
float r;
|
||||||
|
};
|
||||||
|
MaterialData* materialDatas = new MaterialData[3000];
|
||||||
|
for (int i = 0; i < 3000; i++) {
|
||||||
|
materialDatas[i].r = srandom() * 0.1f + 0.1f;
|
||||||
|
}
|
||||||
|
UpdateConstantBuffer(sb, materialDatas, sizeof(MaterialData) * 3000);
|
||||||
|
|
||||||
|
int imageWidth, imageHeight, imageChannel;
|
||||||
|
stbi_uc* pixels = stbi_load("Res/Image/earth_d.jpg", &imageWidth, &imageHeight, &imageChannel, 4);
|
||||||
|
ID3D12Resource* texture = CreateTexture2D(commandList, pixels,
|
||||||
|
imageWidth * imageHeight * imageChannel, imageWidth, imageHeight, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||||
|
delete[] pixels;
|
||||||
|
ID3D12Device* d3dDevice = GetD3DDevice();
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* srvHeap = nullptr;
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescSRV = {};
|
||||||
|
d3dDescriptorHeapDescSRV.NumDescriptors = 3;
|
||||||
|
d3dDescriptorHeapDescSRV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||||
|
d3dDescriptorHeapDescSRV.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||||
|
d3dDevice->CreateDescriptorHeap(&d3dDescriptorHeapDescSRV, IID_PPV_ARGS(&srvHeap));
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* descriptorHeaps[] = { srvHeap };
|
||||||
|
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
|
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MipLevels = 1;
|
||||||
|
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE srvHeapPtr = srvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
d3dDevice->CreateShaderResourceView(texture, &srvDesc, srvHeapPtr);
|
||||||
|
srvHeapPtr.ptr += d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||||
|
|
||||||
|
EndCommandList();
|
||||||
|
WaitForCompletionOfCommandList();
|
||||||
|
|
||||||
|
ShowWindow(hwnd, inShowCmd);
|
||||||
|
UpdateWindow(hwnd);
|
||||||
|
float color[] = { 0.5f,0.5f,0.5f,1.0f };
|
||||||
|
MSG msg;
|
||||||
|
DWORD last_time = timeGetTime();
|
||||||
|
DWORD appStartTime = last_time;
|
||||||
|
while (true) {
|
||||||
|
ZeroMemory(&msg, sizeof(MSG));
|
||||||
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
if (msg.message == WM_QUIT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
} else {
|
||||||
|
WaitForCompletionOfCommandList();
|
||||||
|
DWORD current_time = timeGetTime();
|
||||||
|
DWORD frameTime = current_time - last_time;
|
||||||
|
DWORD timeSinceAppStartInMS = current_time - appStartTime;
|
||||||
|
last_time = current_time;
|
||||||
|
float frameTimeInSecond = float(frameTime) / 1000.0f;
|
||||||
|
float timeSinceAppStartInSecond = float(timeSinceAppStartInMS) / 1000.0f;
|
||||||
|
color[0] = timeSinceAppStartInSecond;
|
||||||
|
commandAllocator->Reset();
|
||||||
|
commandList->Reset(commandAllocator, nullptr);
|
||||||
|
BeginRenderToSwapChain(commandList);
|
||||||
|
commandList->SetPipelineState(pso);
|
||||||
|
commandList->SetGraphicsRootSignature(rootSignature);
|
||||||
|
commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
|
||||||
|
commandList->SetGraphicsRootConstantBufferView(0, cb->GetGPUVirtualAddress());
|
||||||
|
commandList->SetGraphicsRoot32BitConstants(1, 4, color, 0);
|
||||||
|
commandList->SetGraphicsRootDescriptorTable(2, srvHeap->GetGPUDescriptorHandleForHeapStart());
|
||||||
|
commandList->SetGraphicsRootShaderResourceView(3, sb->GetGPUVirtualAddress());
|
||||||
|
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
staticMeshComponent.Render(commandList);
|
||||||
|
EndRenderToSwapChain(commandList);
|
||||||
|
EndCommandList();
|
||||||
|
SwapD3D12Buffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
2
tests/D3D12/stbi/stb_image.cpp
Normal file
2
tests/D3D12/stbi/stb_image.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
7194
tests/D3D12/stbi/stb_image.h
Normal file
7194
tests/D3D12/stbi/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user