From 787403337949f9b39b6d093be1a76457cb49abc5 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 17 Mar 2026 00:52:24 +0800 Subject: [PATCH] Add RootSignatureBuilder and PipelineStateBuilder for cleaner RHI API --- D3D12_engine_log.txt | 8 + engine/CMakeLists.txt | 4 + .../XCEngine/RHI/D3D12/D3D12PipelineState.h | 1 - .../XCEngine/RHI/D3D12/D3D12QueryHeap.h | 1 - .../XCEngine/RHI/D3D12/D3D12RootSignature.h | 1 - .../include/XCEngine/RHI/D3D12/D3D12Sampler.h | 1 - .../XCEngine/RHI/D3D12/PipelineStateBuilder.h | 53 ++++++ .../XCEngine/RHI/D3D12/RootSignatureBuilder.h | 30 ++++ engine/src/RHI/D3D12/PipelineStateBuilder.cpp | 159 ++++++++++++++++++ engine/src/RHI/D3D12/RootSignatureBuilder.cpp | 84 +++++++++ 10 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 engine/include/XCEngine/RHI/D3D12/PipelineStateBuilder.h create mode 100644 engine/include/XCEngine/RHI/D3D12/RootSignatureBuilder.h create mode 100644 engine/src/RHI/D3D12/PipelineStateBuilder.cpp create mode 100644 engine/src/RHI/D3D12/RootSignatureBuilder.cpp diff --git a/D3D12_engine_log.txt b/D3D12_engine_log.txt index 125b6b67..59e17d65 100644 --- a/D3D12_engine_log.txt +++ b/D3D12_engine_log.txt @@ -14,3 +14,11 @@ [2026-03-16 13:25:13] [DEBUG] [Rendering] [DEBUG] WaitForCompletion: completed=1, waiting for=1 +[2026-03-17 00:39:42] [DEBUG] [Rendering] [DEBUG] D3D12 Test Application Started + +[2026-03-17 00:39:42] [DEBUG] [Rendering] [DEBUG] Texture loaded: width=-858993460, height=-858993460, channels=-858993460, pixels=0000000000000000 + +[2026-03-17 00:39:42] [DEBUG] [Rendering] [DEBUG] WaitForCompletion: completed=1, waiting for=1 + +[2026-03-17 00:39:42] [DEBUG] [Rendering] [DEBUG] WaitForCompletion: completed=1, waiting for=1 + diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 42719b05..8274bdcd 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -95,6 +95,8 @@ add_library(XCEngine STATIC include/XCEngine/RHI/D3D12/D3D12Shader.h include/XCEngine/RHI/D3D12/D3D12Texture.h include/XCEngine/RHI/D3D12/D3D12RootSignature.h + include/XCEngine/RHI/D3D12/RootSignatureBuilder.h + include/XCEngine/RHI/D3D12/PipelineStateBuilder.h include/XCEngine/RHI/D3D12/D3D12SwapChain.h include/XCEngine/RHI/D3D12/D3D12Fence.h include/XCEngine/RHI/D3D12/D3D12Screenshot.h @@ -115,6 +117,8 @@ add_library(XCEngine STATIC src/RHI/D3D12/D3D12Shader.cpp src/RHI/D3D12/D3D12Texture.cpp src/RHI/D3D12/D3D12RootSignature.cpp + src/RHI/D3D12/RootSignatureBuilder.cpp + src/RHI/D3D12/PipelineStateBuilder.cpp src/RHI/D3D12/D3D12SwapChain.cpp src/RHI/D3D12/D3D12Fence.cpp src/RHI/D3D12/D3D12Screenshot.cpp diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12PipelineState.h b/engine/include/XCEngine/RHI/D3D12/D3D12PipelineState.h index 29a0c04d..b5ca8f49 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12PipelineState.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12PipelineState.h @@ -3,7 +3,6 @@ #include #include -#include "../DescriptorHeap.h" #include "D3D12Enum.h" using Microsoft::WRL::ComPtr; diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h b/engine/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h index c8991c95..1ac947b9 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h @@ -4,7 +4,6 @@ #include #include -#include "../DescriptorHeap.h" #include "D3D12Enum.h" using Microsoft::WRL::ComPtr; diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12RootSignature.h b/engine/include/XCEngine/RHI/D3D12/D3D12RootSignature.h index fa6b83de..62ba5e66 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12RootSignature.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12RootSignature.h @@ -4,7 +4,6 @@ #include #include "../Enums.h" -#include "../DescriptorHeap.h" #include "D3D12Enum.h" using Microsoft::WRL::ComPtr; diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12Sampler.h b/engine/include/XCEngine/RHI/D3D12/D3D12Sampler.h index 58d430a8..e480fd8e 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12Sampler.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12Sampler.h @@ -3,7 +3,6 @@ #include #include -#include "../DescriptorHeap.h" #include "D3D12Enum.h" using Microsoft::WRL::ComPtr; diff --git a/engine/include/XCEngine/RHI/D3D12/PipelineStateBuilder.h b/engine/include/XCEngine/RHI/D3D12/PipelineStateBuilder.h new file mode 100644 index 00000000..47f506a4 --- /dev/null +++ b/engine/include/XCEngine/RHI/D3D12/PipelineStateBuilder.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include "../Enums.h" +#include "D3D12Enum.h" + +namespace XCEngine { +namespace RHI { + +class PipelineStateBuilder { +public: + PipelineStateBuilder(); + + PipelineStateBuilder& SetRootSignature(ID3D12RootSignature* rootSignature); + PipelineStateBuilder& SetVertexShader(const D3D12_SHADER_BYTECODE& shader); + PipelineStateBuilder& SetPixelShader(const D3D12_SHADER_BYTECODE& shader); + PipelineStateBuilder& SetGeometryShader(const D3D12_SHADER_BYTECODE& shader); + + PipelineStateBuilder& SetInputLayout(uint32_t numElements, const D3D12_INPUT_ELEMENT_DESC* elements); + PipelineStateBuilder& SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE topologyType); + + PipelineStateBuilder& SetRenderTargetFormat(Format format); + PipelineStateBuilder& SetRenderTargetFormats(uint32_t count, const Format* formats); + PipelineStateBuilder& SetDepthStencilFormat(Format format); + + PipelineStateBuilder& SetSampleDesc(uint32_t count, uint32_t quality); + + PipelineStateBuilder& SetFillMode(FillMode mode); + PipelineStateBuilder& SetCullMode(CullMode mode); + PipelineStateBuilder& SetDepthClipEnable(bool enable); + + PipelineStateBuilder& SetDepthEnable(bool enable); + PipelineStateBuilder& SetDepthWriteMask(D3D12_DEPTH_WRITE_MASK writeMask); + PipelineStateBuilder& SetDepthFunc(ComparisonFunc func); + + PipelineStateBuilder& SetStencilEnable(bool enable); + PipelineStateBuilder& SetFrontFaceStencilOp(D3D12_STENCIL_OP failOp, D3D12_STENCIL_OP depthFailOp, D3D12_STENCIL_OP passOp, ComparisonFunc func); + PipelineStateBuilder& SetBackFaceStencilOp(D3D12_STENCIL_OP failOp, D3D12_STENCIL_OP depthFailOp, D3D12_STENCIL_OP passOp, ComparisonFunc func); + + PipelineStateBuilder& SetBlendEnable(bool enable); + PipelineStateBuilder& SetBlendFactor(BlendFactor srcBlend, BlendFactor dstBlend, BlendOp blendOp); + PipelineStateBuilder& SetAlphaBlendFactor(BlendFactor srcBlendAlpha, BlendFactor dstBlendAlpha, BlendOp blendOpAlpha); + PipelineStateBuilder& SetColorWriteMask(ColorWriteMask mask); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC Build(); + +private: + D3D12_GRAPHICS_PIPELINE_STATE_DESC m_desc; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/D3D12/RootSignatureBuilder.h b/engine/include/XCEngine/RHI/D3D12/RootSignatureBuilder.h new file mode 100644 index 00000000..b59a4ae1 --- /dev/null +++ b/engine/include/XCEngine/RHI/D3D12/RootSignatureBuilder.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include "../Enums.h" +#include "D3D12Enum.h" + +namespace XCEngine { +namespace RHI { + +class RootSignatureBuilder { +public: + RootSignatureBuilder(); + + RootSignatureBuilder& AddCBV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0); + RootSignatureBuilder& AddSRV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0); + RootSignatureBuilder& AddUAV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0); + RootSignatureBuilder& Add32BitConstants(uint32_t shaderRegister, uint32_t num32BitValues, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0); + RootSignatureBuilder& AddDescriptorTable(uint32_t shaderRegister, uint32_t numDescriptors, D3D12_DESCRIPTOR_RANGE_TYPE rangeType, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0); + + D3D12_ROOT_SIGNATURE_DESC Build(); + +private: + std::vector m_parameters; + std::vector> m_descriptorRanges; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/D3D12/PipelineStateBuilder.cpp b/engine/src/RHI/D3D12/PipelineStateBuilder.cpp new file mode 100644 index 00000000..908ef107 --- /dev/null +++ b/engine/src/RHI/D3D12/PipelineStateBuilder.cpp @@ -0,0 +1,159 @@ +#include "XCEngine/RHI/D3D12/PipelineStateBuilder.h" + +namespace XCEngine { +namespace RHI { + +PipelineStateBuilder::PipelineStateBuilder() { + memset(&m_desc, 0, sizeof(m_desc)); + m_desc.SampleDesc.Count = 1; + m_desc.SampleDesc.Quality = 0; + m_desc.SampleMask = 0xffffffff; + m_desc.NumRenderTargets = 1; + m_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + m_desc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + m_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + m_desc.DepthStencilState.DepthEnable = TRUE; + m_desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + m_desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + m_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; + m_desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; + m_desc.RasterizerState.DepthClipEnable = TRUE; +} + +PipelineStateBuilder& PipelineStateBuilder::SetRootSignature(ID3D12RootSignature* rootSignature) { + m_desc.pRootSignature = rootSignature; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetVertexShader(const D3D12_SHADER_BYTECODE& shader) { + m_desc.VS = shader; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetPixelShader(const D3D12_SHADER_BYTECODE& shader) { + m_desc.PS = shader; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetGeometryShader(const D3D12_SHADER_BYTECODE& shader) { + m_desc.GS = shader; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetInputLayout(uint32_t numElements, const D3D12_INPUT_ELEMENT_DESC* elements) { + m_desc.InputLayout.NumElements = numElements; + m_desc.InputLayout.pInputElementDescs = elements; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE topologyType) { + m_desc.PrimitiveTopologyType = topologyType; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetRenderTargetFormat(Format format) { + m_desc.NumRenderTargets = 1; + m_desc.RTVFormats[0] = ToD3D12(format); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetRenderTargetFormats(uint32_t count, const Format* formats) { + m_desc.NumRenderTargets = count; + for (uint32_t i = 0; i < count && i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { + m_desc.RTVFormats[i] = ToD3D12(formats[i]); + } + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetDepthStencilFormat(Format format) { + m_desc.DSVFormat = ToD3D12(format); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetSampleDesc(uint32_t count, uint32_t quality) { + m_desc.SampleDesc.Count = count; + m_desc.SampleDesc.Quality = quality; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetFillMode(FillMode mode) { + m_desc.RasterizerState.FillMode = ToD3D12(mode); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetCullMode(CullMode mode) { + m_desc.RasterizerState.CullMode = ToD3D12(mode); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetDepthClipEnable(bool enable) { + m_desc.RasterizerState.DepthClipEnable = enable ? TRUE : FALSE; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetDepthEnable(bool enable) { + m_desc.DepthStencilState.DepthEnable = enable ? TRUE : FALSE; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetDepthWriteMask(D3D12_DEPTH_WRITE_MASK writeMask) { + m_desc.DepthStencilState.DepthWriteMask = writeMask; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetDepthFunc(ComparisonFunc func) { + m_desc.DepthStencilState.DepthFunc = ToD3D12(func); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetStencilEnable(bool enable) { + m_desc.DepthStencilState.StencilEnable = enable ? TRUE : FALSE; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetFrontFaceStencilOp(D3D12_STENCIL_OP failOp, D3D12_STENCIL_OP depthFailOp, D3D12_STENCIL_OP passOp, ComparisonFunc func) { + m_desc.DepthStencilState.FrontFace.StencilFailOp = failOp; + m_desc.DepthStencilState.FrontFace.StencilDepthFailOp = depthFailOp; + m_desc.DepthStencilState.FrontFace.StencilPassOp = passOp; + m_desc.DepthStencilState.FrontFace.StencilFunc = ToD3D12(func); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetBackFaceStencilOp(D3D12_STENCIL_OP failOp, D3D12_STENCIL_OP depthFailOp, D3D12_STENCIL_OP passOp, ComparisonFunc func) { + m_desc.DepthStencilState.BackFace.StencilFailOp = failOp; + m_desc.DepthStencilState.BackFace.StencilDepthFailOp = depthFailOp; + m_desc.DepthStencilState.BackFace.StencilPassOp = passOp; + m_desc.DepthStencilState.BackFace.StencilFunc = ToD3D12(func); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetBlendEnable(bool enable) { + m_desc.BlendState.RenderTarget[0].BlendEnable = enable ? TRUE : FALSE; + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetBlendFactor(BlendFactor srcBlend, BlendFactor dstBlend, BlendOp blendOp) { + m_desc.BlendState.RenderTarget[0].SrcBlend = ToD3D12(srcBlend); + m_desc.BlendState.RenderTarget[0].DestBlend = ToD3D12(dstBlend); + m_desc.BlendState.RenderTarget[0].BlendOp = ToD3D12(blendOp); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetAlphaBlendFactor(BlendFactor srcBlendAlpha, BlendFactor dstBlendAlpha, BlendOp blendOpAlpha) { + m_desc.BlendState.RenderTarget[0].SrcBlendAlpha = ToD3D12(srcBlendAlpha); + m_desc.BlendState.RenderTarget[0].DestBlendAlpha = ToD3D12(dstBlendAlpha); + m_desc.BlendState.RenderTarget[0].BlendOpAlpha = ToD3D12(blendOpAlpha); + return *this; +} + +PipelineStateBuilder& PipelineStateBuilder::SetColorWriteMask(ColorWriteMask mask) { + m_desc.BlendState.RenderTarget[0].RenderTargetWriteMask = static_cast(mask); + return *this; +} + +D3D12_GRAPHICS_PIPELINE_STATE_DESC PipelineStateBuilder::Build() { + return m_desc; +} + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/D3D12/RootSignatureBuilder.cpp b/engine/src/RHI/D3D12/RootSignatureBuilder.cpp new file mode 100644 index 00000000..61799eb8 --- /dev/null +++ b/engine/src/RHI/D3D12/RootSignatureBuilder.cpp @@ -0,0 +1,84 @@ +#include "XCEngine/RHI/D3D12/RootSignatureBuilder.h" + +namespace XCEngine { +namespace RHI { + +RootSignatureBuilder::RootSignatureBuilder() { + m_parameters.reserve(8); + m_descriptorRanges.reserve(8); +} + +RootSignatureBuilder& RootSignatureBuilder::AddCBV(uint32_t shaderRegister, ShaderVisibility visibility, uint32_t registerSpace) { + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + param.ShaderVisibility = ToD3D12(visibility); + param.Descriptor.RegisterSpace = registerSpace; + param.Descriptor.ShaderRegister = shaderRegister; + m_parameters.push_back(param); + return *this; +} + +RootSignatureBuilder& RootSignatureBuilder::AddSRV(uint32_t shaderRegister, ShaderVisibility visibility, uint32_t registerSpace) { + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + param.ShaderVisibility = ToD3D12(visibility); + param.Descriptor.RegisterSpace = registerSpace; + param.Descriptor.ShaderRegister = shaderRegister; + m_parameters.push_back(param); + return *this; +} + +RootSignatureBuilder& RootSignatureBuilder::AddUAV(uint32_t shaderRegister, ShaderVisibility visibility, uint32_t registerSpace) { + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + param.ShaderVisibility = ToD3D12(visibility); + param.Descriptor.RegisterSpace = registerSpace; + param.Descriptor.ShaderRegister = shaderRegister; + m_parameters.push_back(param); + return *this; +} + +RootSignatureBuilder& RootSignatureBuilder::Add32BitConstants(uint32_t shaderRegister, uint32_t num32BitValues, ShaderVisibility visibility, uint32_t registerSpace) { + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + param.ShaderVisibility = ToD3D12(visibility); + param.Constants.RegisterSpace = registerSpace; + param.Constants.ShaderRegister = shaderRegister; + param.Constants.Num32BitValues = num32BitValues; + m_parameters.push_back(param); + return *this; +} + +RootSignatureBuilder& RootSignatureBuilder::AddDescriptorTable(uint32_t shaderRegister, uint32_t numDescriptors, D3D12_DESCRIPTOR_RANGE_TYPE rangeType, ShaderVisibility visibility, uint32_t registerSpace) { + D3D12_DESCRIPTOR_RANGE range = {}; + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = shaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + std::vector ranges; + ranges.push_back(range); + m_descriptorRanges.push_back(ranges); + + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param.ShaderVisibility = ToD3D12(visibility); + param.DescriptorTable.NumDescriptorRanges = static_cast(m_descriptorRanges.back().size()); + param.DescriptorTable.pDescriptorRanges = m_descriptorRanges.back().data(); + m_parameters.push_back(param); + return *this; +} + +D3D12_ROOT_SIGNATURE_DESC RootSignatureBuilder::Build() { + D3D12_ROOT_SIGNATURE_DESC desc = {}; + desc.NumParameters = static_cast(m_parameters.size()); + desc.pParameters = m_parameters.data(); + desc.NumStaticSamplers = 0; + desc.pStaticSamplers = nullptr; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + return desc; +} + +} // namespace RHI +} // namespace XCEngine