refactor(RHI): complete PipelineState Unity SRP style refactoring

- Fix Chinese character encoding issues causing MSVC C4819 warnings
- Add m_rootSignature member to D3D12PipelineState for PSO creation
- All integration tests pass: OpenGL 4/4, D3D12 4/4
- All RHI unit tests pass: 158/158
This commit is contained in:
2026-03-24 18:33:16 +08:00
parent 6ed033890a
commit c66ba2feb3
14 changed files with 516 additions and 300 deletions

View File

@@ -68,7 +68,7 @@ public:
RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
RHIShader* CompileShader(const ShaderCompileDesc& desc) override;
RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) override;
RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) override;
RHIFence* CreateFence(const FenceDesc& desc) override;
RHISampler* CreateSampler(const SamplerDesc& desc) override;

View File

@@ -3,8 +3,10 @@
#include <d3d12.h>
#include <dxgi1_4.h>
#include <wrl/client.h>
#include <vector>
#include "../RHIPipelineState.h"
#include "../RHITypes.h"
#include "../RHIEnums.h"
#include "D3D12Enums.h"
@@ -15,28 +17,45 @@ namespace RHI {
class D3D12PipelineState : public RHIPipelineState {
public:
D3D12PipelineState();
D3D12PipelineState() = default;
D3D12PipelineState(ID3D12Device* device);
~D3D12PipelineState() override;
bool Initialize(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC& desc);
// State configuration (Unity SRP style)
void SetInputLayout(const InputLayoutDesc& layout) override;
void SetRasterizerState(const RasterizerDesc& state) override;
void SetBlendState(const BlendDesc& state) override;
void SetDepthStencilState(const DepthStencilStateDesc& state) override;
void SetTopology(uint32_t topologyType) override;
void SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) override;
void SetSampleCount(uint32_t count) override;
// State query
const RasterizerDesc& GetRasterizerState() const override { return m_rasterizerDesc; }
const BlendDesc& GetBlendState() const override { return m_blendDesc; }
const DepthStencilStateDesc& GetDepthStencilState() const override { return m_depthStencilDesc; }
const InputLayoutDesc& GetInputLayout() const override { return m_inputLayoutDesc; }
PipelineStateHash GetHash() const override;
// Finalization
bool IsFinalized() const override { return m_finalized; }
bool Finalize() override;
// Shader Bytecode (set by CommandList when binding)
void SetShaderBytecodes(const D3D12_SHADER_BYTECODE& vs, const D3D12_SHADER_BYTECODE& ps, const D3D12_SHADER_BYTECODE& gs = {});
// Lifecycle
void Shutdown() override;
ID3D12PipelineState* GetPipelineState() const { return m_pipelineState.Get(); }
void* GetNativeHandle() override { return m_pipelineState.Get(); }
PipelineType GetType() const override { return PipelineType::Graphics; }
void Bind() override;
void Unbind() override;
static D3D12_GRAPHICS_PIPELINE_STATE_DESC CreateDesc(
ID3D12RootSignature* rootSignature,
const D3D12_SHADER_BYTECODE& vs,
const D3D12_SHADER_BYTECODE& ps,
const D3D12_SHADER_BYTECODE& gs,
uint32_t inputElementCount,
const D3D12_INPUT_ELEMENT_DESC* inputElements);
// Helper functions
static D3D12_INPUT_ELEMENT_DESC CreateInputElement(
const char* semanticName,
uint32_t semanticIndex,
@@ -51,7 +70,32 @@ public:
uint32_t inputSlot);
private:
bool CreateD3D12PSO();
ID3D12Device* m_device;
bool m_finalized = false;
// Stored configuration (Unity SRP style)
GraphicsPipelineDesc m_desc;
InputLayoutDesc m_inputLayoutDesc;
RasterizerDesc m_rasterizerDesc;
BlendDesc m_blendDesc;
DepthStencilStateDesc m_depthStencilDesc;
uint32_t m_topologyType = 0;
uint32_t m_renderTargetCount = 1;
uint32_t m_renderTargetFormats[8] = { 0 };
uint32_t m_depthStencilFormat = 0;
uint32_t m_sampleCount = 1;
// Shader bytecodes (set externally)
D3D12_SHADER_BYTECODE m_vsBytecode = {};
D3D12_SHADER_BYTECODE m_psBytecode = {};
D3D12_SHADER_BYTECODE m_gsBytecode = {};
ID3D12RootSignature* m_rootSignature = nullptr;
// D3D12 resources
ComPtr<ID3D12PipelineState> m_pipelineState;
std::vector<D3D12_INPUT_ELEMENT_DESC> m_inputElements;
};
} // namespace RHI

View File

@@ -56,7 +56,7 @@ public:
void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override;
void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override;
// OpenGL 特有版本(底层逃逸)
// OpenGL specific version (low-level escape hatch)
void SetVertexBuffer(unsigned int buffer, size_t offset, size_t stride);
void SetVertexBuffers(unsigned int startSlot, unsigned int count, const unsigned int* buffers, const size_t* offsets, const size_t* strides);
void SetIndexBuffer(unsigned int buffer, unsigned int type);

View File

@@ -49,7 +49,7 @@ public:
RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
RHIShader* CompileShader(const ShaderCompileDesc& desc) override;
RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) override;
RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) override;
RHIFence* CreateFence(const FenceDesc& desc) override;
RHISampler* CreateSampler(const SamplerDesc& desc) override;

View File

@@ -4,44 +4,12 @@
#include <string>
#include "../RHIPipelineState.h"
#include "../RHITypes.h"
#include "../RHIEnums.h"
namespace XCEngine {
namespace RHI {
enum class OpenGLPrimitiveTopology {
Points,
Lines,
LineStrip,
Triangles,
TriangleStrip
};
enum class OpenGLBlendOp {
Add,
Subtract,
ReverseSubtract,
Min,
Max
};
enum class CullFace {
Front,
Back,
FrontAndBack
};
enum class FrontFace {
Clockwise,
CounterClockwise
};
enum class PolygonMode {
Point,
Line,
Fill
};
struct OpenGLDepthStencilState {
bool depthTestEnable = true;
bool depthWriteEnable = true;
@@ -70,9 +38,9 @@ struct OpenGLBlendState {
struct OpenGLRasterizerState {
bool cullFaceEnable = true;
CullFace cullFace = CullFace::Back;
CullMode cullFace = CullMode::Back;
FrontFace frontFace = FrontFace::CounterClockwise;
PolygonMode polygonMode = PolygonMode::Fill;
FillMode polygonMode = FillMode::Solid;
float polygonOffsetFactor = 0.0f;
float polygonOffsetUnits = 0.0f;
bool depthClipEnable = true;
@@ -98,58 +66,79 @@ struct ScissorState {
int height = 0;
};
struct LogicalOperation {
bool enable = false;
uint32_t operation = 0;
};
class OpenGLPipelineState : public RHIPipelineState {
public:
OpenGLPipelineState();
~OpenGLPipelineState() override;
// State configuration (Unity SRP style)
void SetInputLayout(const InputLayoutDesc& layout) override;
void SetRasterizerState(const RasterizerDesc& state) override;
void SetBlendState(const BlendDesc& state) override;
void SetDepthStencilState(const DepthStencilStateDesc& state) override;
void SetTopology(uint32_t topologyType) override;
void SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) override;
void SetSampleCount(uint32_t count) override;
// State query
const RasterizerDesc& GetRasterizerState() const override { return m_rasterizerDesc; }
const BlendDesc& GetBlendState() const override { return m_blendDesc; }
const DepthStencilStateDesc& GetDepthStencilState() const override { return m_depthStencilDesc; }
const InputLayoutDesc& GetInputLayout() const override { return m_inputLayoutDesc; }
PipelineStateHash GetHash() const override;
// Finalization (OpenGL doesn't need it)
bool IsFinalized() const override { return true; }
bool Finalize() override { return true; }
// Lifecycle
void Shutdown() override;
void* GetNativeHandle() override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_program)); }
PipelineType GetType() const override { return PipelineType::Graphics; }
void Bind() override;
void Unbind() override;
void* GetNativeHandle() override;
PipelineType GetType() const override { return PipelineType::Graphics; }
void SetDepthStencilState(const OpenGLDepthStencilState& state);
void SetBlendState(const OpenGLBlendState& state);
void SetRasterizerState(const OpenGLRasterizerState& state);
void SetViewport(const ViewportState& state);
void SetScissor(const ScissorState& state);
void SetLogicalOperation(const LogicalOperation& state);
// OpenGL specific
void Apply();
void ApplyDepthStencil();
void ApplyBlend();
void ApplyRasterizer();
void ApplyViewport();
void ApplyScissor();
void SetProgram(unsigned int program);
unsigned int GetProgram() const { return m_program; }
void SetDepthStencilState(const OpenGLDepthStencilState& state);
void SetBlendState(const OpenGLBlendState& state);
void SetRasterizerState(const OpenGLRasterizerState& state);
void SetViewport(const ViewportState& state);
void SetScissor(const ScissorState& state);
void SetClearColor(float r, float g, float b, float a);
void Clear(unsigned int buffers);
void AttachShader(unsigned int program);
void DetachShader();
const OpenGLDepthStencilState& GetDepthStencilState() const { return m_depthStencilState; }
const OpenGLBlendState& GetBlendState() const { return m_blendState; }
const OpenGLRasterizerState& GetRasterizerState() const { return m_rasterizerState; }
const OpenGLDepthStencilState& GetOpenGLDepthStencilState() const;
const OpenGLBlendState& GetOpenGLBlendState() const;
const OpenGLRasterizerState& GetOpenGLRasterizerState() const;
private:
OpenGLDepthStencilState m_depthStencilState;
OpenGLBlendState m_blendState;
OpenGLRasterizerState m_rasterizerState;
InputLayoutDesc m_inputLayoutDesc;
RasterizerDesc m_rasterizerDesc;
BlendDesc m_blendDesc;
DepthStencilStateDesc m_depthStencilDesc;
uint32_t m_topologyType = 0;
unsigned int m_program = 0;
bool m_programAttached = false;
// OpenGL specific state
OpenGLDepthStencilState m_glDepthStencilState;
OpenGLBlendState m_glBlendState;
OpenGLRasterizerState m_glRasterizerState;
ViewportState m_viewportState;
ScissorState m_scissorState;
LogicalOperation m_logicalOperation;
float m_clearColor[4];
unsigned int m_program;
bool m_programAttached;
float m_clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
};
} // namespace RHI

View File

@@ -31,7 +31,7 @@ public:
virtual RHICommandList* CreateCommandList(const CommandListDesc& desc) = 0;
virtual RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0;
virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0;
virtual RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) = 0;
virtual RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) = 0;
virtual RHIFence* CreateFence(const FenceDesc& desc) = 0;
virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0;

View File

@@ -30,6 +30,11 @@ enum class FillMode : uint8_t {
Solid
};
enum class FrontFace : uint8_t {
Clockwise,
CounterClockwise
};
enum class BlendOp : uint8_t {
Add,
Subtract,
@@ -155,6 +160,14 @@ enum class PrimitiveTopology : uint8_t {
PatchList
};
enum class PrimitiveTopologyType : uint8_t {
Undefined,
Point,
Line,
Triangle,
Patch
};
enum class FilterMode : uint8_t {
Point,
Linear,

View File

@@ -10,11 +10,30 @@ class RHIPipelineState {
public:
virtual ~RHIPipelineState() = default;
virtual void Shutdown() = 0;
// State configuration (Unity SRP style - Shader independent of PSO)
virtual void SetInputLayout(const InputLayoutDesc& layout) = 0;
virtual void SetRasterizerState(const RasterizerDesc& state) = 0;
virtual void SetBlendState(const BlendDesc& state) = 0;
virtual void SetDepthStencilState(const DepthStencilStateDesc& state) = 0;
virtual void SetTopology(uint32_t topologyType) = 0; // PrimitiveTopologyType
virtual void SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) = 0;
virtual void SetSampleCount(uint32_t count) = 0;
// State query
virtual const RasterizerDesc& GetRasterizerState() const = 0;
virtual const BlendDesc& GetBlendState() const = 0;
virtual const DepthStencilStateDesc& GetDepthStencilState() const = 0;
virtual const InputLayoutDesc& GetInputLayout() const = 0;
virtual PipelineStateHash GetHash() const = 0;
// Finalization (D3D12/Vulkan creates real PSO)
virtual bool IsFinalized() const = 0;
virtual bool Finalize() = 0;
// Lifecycle
virtual void Shutdown() = 0;
virtual void Bind() = 0;
virtual void Unbind() = 0;
virtual void* GetNativeHandle() = 0;
virtual PipelineType GetType() const = 0;
};

View File

@@ -236,9 +236,81 @@ struct RootSignatureDesc {
uint32_t size;
};
struct PipelineStateDesc {
const void* pBlob;
uint32_t size;
// ========== Pipeline State Structures (Unity SRP style) ==========
struct StencilOpDesc {
uint32_t failOp = 0; // StencilOp
uint32_t passOp = 0; // StencilOp
uint32_t depthFailOp = 0; // StencilOp
uint32_t func = 0; // ComparisonFunc
};
struct DepthStencilStateDesc {
bool depthTestEnable = true;
bool depthWriteEnable = true;
bool depthBoundsEnable = false;
uint32_t depthFunc = 0; // ComparisonFunc
bool stencilEnable = false;
uint8_t stencilReadMask = 0xFF;
uint8_t stencilWriteMask = 0xFF;
StencilOpDesc front;
StencilOpDesc back;
};
struct BlendDesc {
bool blendEnable = false;
uint32_t srcBlend = 0; // BlendFactor
uint32_t dstBlend = 0; // BlendFactor
uint32_t srcBlendAlpha = 0; // BlendFactor
uint32_t dstBlendAlpha = 0; // BlendFactor
uint32_t blendOp = 0; // BlendOp
uint32_t blendOpAlpha = 0; // BlendOp
uint8_t colorWriteMask = 0xF;
float blendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
};
struct RasterizerDesc {
uint32_t fillMode = 0; // FillMode (default: Solid)
uint32_t cullMode = 0; // CullMode (default: Back)
uint32_t frontFace = 0; // FrontFace (default: CounterClockwise)
bool depthClipEnable = true;
bool scissorTestEnable = false;
bool multisampleEnable = false;
bool antialiasedLineEnable = false;
int depthBias = 0;
float depthBiasClamp = 0.0f;
float slopeScaledDepthBias = 0.0f;
};
struct PipelineStateHash {
uint64_t blendStateHash = 0;
uint64_t depthStateHash = 0;
uint64_t rasterizerStateHash = 0;
uint64_t inputLayoutHash = 0;
uint64_t topologyHash = 0;
uint64_t renderTargetHash = 0;
bool operator==(const PipelineStateHash& other) const {
return blendStateHash == other.blendStateHash &&
depthStateHash == other.depthStateHash &&
rasterizerStateHash == other.rasterizerStateHash &&
inputLayoutHash == other.inputLayoutHash &&
topologyHash == other.topologyHash &&
renderTargetHash == other.renderTargetHash;
}
};
struct GraphicsPipelineDesc {
InputLayoutDesc inputLayout;
RasterizerDesc rasterizerState;
BlendDesc blendState;
DepthStencilStateDesc depthStencilState;
uint32_t topologyType = 0; // PrimitiveTopologyType
uint32_t renderTargetCount = 1;
uint32_t renderTargetFormats[8] = { 0 }; // Format
uint32_t depthStencilFormat = 0; // Format
uint32_t sampleCount = 1;
};
struct RHIDeviceDesc {