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

@@ -60,6 +60,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
d3d12.lib d3d12.lib
dxgi.lib dxgi.lib
d3dcompiler.lib d3dcompiler.lib
XCEngine
) )
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES

View File

@@ -68,7 +68,7 @@ public:
RHICommandList* CreateCommandList(const CommandListDesc& desc) override; RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override; RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
RHIShader* CompileShader(const ShaderCompileDesc& 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; RHIFence* CreateFence(const FenceDesc& desc) override;
RHISampler* CreateSampler(const SamplerDesc& desc) override; RHISampler* CreateSampler(const SamplerDesc& desc) override;

View File

@@ -3,8 +3,10 @@
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_4.h> #include <dxgi1_4.h>
#include <wrl/client.h> #include <wrl/client.h>
#include <vector>
#include "../RHIPipelineState.h" #include "../RHIPipelineState.h"
#include "../RHITypes.h"
#include "../RHIEnums.h" #include "../RHIEnums.h"
#include "D3D12Enums.h" #include "D3D12Enums.h"
@@ -15,28 +17,45 @@ namespace RHI {
class D3D12PipelineState : public RHIPipelineState { class D3D12PipelineState : public RHIPipelineState {
public: public:
D3D12PipelineState(); D3D12PipelineState() = default;
D3D12PipelineState(ID3D12Device* device);
~D3D12PipelineState() override; ~D3D12PipelineState() override;
bool Initialize(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC& desc); 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; void Shutdown() override;
ID3D12PipelineState* GetPipelineState() const { return m_pipelineState.Get(); } ID3D12PipelineState* GetPipelineState() const { return m_pipelineState.Get(); }
void* GetNativeHandle() override { return m_pipelineState.Get(); } void* GetNativeHandle() override { return m_pipelineState.Get(); }
PipelineType GetType() const override { return PipelineType::Graphics; } PipelineType GetType() const override { return PipelineType::Graphics; }
void Bind() override; void Bind() override;
void Unbind() override; void Unbind() override;
static D3D12_GRAPHICS_PIPELINE_STATE_DESC CreateDesc( // Helper functions
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);
static D3D12_INPUT_ELEMENT_DESC CreateInputElement( static D3D12_INPUT_ELEMENT_DESC CreateInputElement(
const char* semanticName, const char* semanticName,
uint32_t semanticIndex, uint32_t semanticIndex,
@@ -51,7 +70,32 @@ public:
uint32_t inputSlot); uint32_t inputSlot);
private: 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; ComPtr<ID3D12PipelineState> m_pipelineState;
std::vector<D3D12_INPUT_ELEMENT_DESC> m_inputElements;
}; };
} // namespace RHI } // 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 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; 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 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 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); void SetIndexBuffer(unsigned int buffer, unsigned int type);

View File

@@ -49,7 +49,7 @@ public:
RHICommandList* CreateCommandList(const CommandListDesc& desc) override; RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override; RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
RHIShader* CompileShader(const ShaderCompileDesc& 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; RHIFence* CreateFence(const FenceDesc& desc) override;
RHISampler* CreateSampler(const SamplerDesc& desc) override; RHISampler* CreateSampler(const SamplerDesc& desc) override;

View File

@@ -4,44 +4,12 @@
#include <string> #include <string>
#include "../RHIPipelineState.h" #include "../RHIPipelineState.h"
#include "../RHITypes.h"
#include "../RHIEnums.h" #include "../RHIEnums.h"
namespace XCEngine { namespace XCEngine {
namespace RHI { 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 { struct OpenGLDepthStencilState {
bool depthTestEnable = true; bool depthTestEnable = true;
bool depthWriteEnable = true; bool depthWriteEnable = true;
@@ -70,9 +38,9 @@ struct OpenGLBlendState {
struct OpenGLRasterizerState { struct OpenGLRasterizerState {
bool cullFaceEnable = true; bool cullFaceEnable = true;
CullFace cullFace = CullFace::Back; CullMode cullFace = CullMode::Back;
FrontFace frontFace = FrontFace::CounterClockwise; FrontFace frontFace = FrontFace::CounterClockwise;
PolygonMode polygonMode = PolygonMode::Fill; FillMode polygonMode = FillMode::Solid;
float polygonOffsetFactor = 0.0f; float polygonOffsetFactor = 0.0f;
float polygonOffsetUnits = 0.0f; float polygonOffsetUnits = 0.0f;
bool depthClipEnable = true; bool depthClipEnable = true;
@@ -98,58 +66,79 @@ struct ScissorState {
int height = 0; int height = 0;
}; };
struct LogicalOperation {
bool enable = false;
uint32_t operation = 0;
};
class OpenGLPipelineState : public RHIPipelineState { class OpenGLPipelineState : public RHIPipelineState {
public: public:
OpenGLPipelineState(); OpenGLPipelineState();
~OpenGLPipelineState() override; ~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 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 Bind() override;
void Unbind() override; void Unbind() override;
void* GetNativeHandle() override; // OpenGL specific
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);
void Apply(); void Apply();
void ApplyDepthStencil(); void ApplyDepthStencil();
void ApplyBlend(); void ApplyBlend();
void ApplyRasterizer(); void ApplyRasterizer();
void ApplyViewport(); void ApplyViewport();
void ApplyScissor(); 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 SetClearColor(float r, float g, float b, float a);
void Clear(unsigned int buffers); void Clear(unsigned int buffers);
void AttachShader(unsigned int program); void AttachShader(unsigned int program);
void DetachShader(); void DetachShader();
const OpenGLDepthStencilState& GetDepthStencilState() const { return m_depthStencilState; } const OpenGLDepthStencilState& GetOpenGLDepthStencilState() const;
const OpenGLBlendState& GetBlendState() const { return m_blendState; } const OpenGLBlendState& GetOpenGLBlendState() const;
const OpenGLRasterizerState& GetRasterizerState() const { return m_rasterizerState; } const OpenGLRasterizerState& GetOpenGLRasterizerState() const;
private: private:
OpenGLDepthStencilState m_depthStencilState; InputLayoutDesc m_inputLayoutDesc;
OpenGLBlendState m_blendState; RasterizerDesc m_rasterizerDesc;
OpenGLRasterizerState m_rasterizerState; 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; ViewportState m_viewportState;
ScissorState m_scissorState; ScissorState m_scissorState;
LogicalOperation m_logicalOperation; float m_clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float m_clearColor[4];
unsigned int m_program;
bool m_programAttached;
}; };
} // namespace RHI } // namespace RHI

View File

@@ -31,7 +31,7 @@ public:
virtual RHICommandList* CreateCommandList(const CommandListDesc& desc) = 0; virtual RHICommandList* CreateCommandList(const CommandListDesc& desc) = 0;
virtual RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0; virtual RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0;
virtual RHIShader* CompileShader(const ShaderCompileDesc& 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 RHIFence* CreateFence(const FenceDesc& desc) = 0;
virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0; virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0;

View File

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

View File

@@ -10,11 +10,30 @@ class RHIPipelineState {
public: public:
virtual ~RHIPipelineState() = default; 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 Bind() = 0;
virtual void Unbind() = 0; virtual void Unbind() = 0;
virtual void* GetNativeHandle() = 0; virtual void* GetNativeHandle() = 0;
virtual PipelineType GetType() const = 0; virtual PipelineType GetType() const = 0;
}; };

View File

@@ -236,9 +236,81 @@ struct RootSignatureDesc {
uint32_t size; uint32_t size;
}; };
struct PipelineStateDesc { // ========== Pipeline State Structures (Unity SRP style) ==========
const void* pBlob;
uint32_t size; 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 { struct RHIDeviceDesc {

View File

@@ -368,8 +368,16 @@ RHICommandQueue* D3D12Device::CreateCommandQueue(const CommandQueueDesc& desc) {
return nullptr; return nullptr;
} }
RHIPipelineState* D3D12Device::CreatePipelineState(const PipelineStateDesc& desc) { RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& desc) {
return nullptr; auto* pso = new D3D12PipelineState(m_device.Get());
pso->SetInputLayout(desc.inputLayout);
pso->SetRasterizerState(desc.rasterizerState);
pso->SetBlendState(desc.blendState);
pso->SetDepthStencilState(desc.depthStencilState);
pso->SetTopology(desc.topologyType);
pso->SetRenderTargetFormats(desc.renderTargetCount, desc.renderTargetFormats, desc.depthStencilFormat);
pso->SetSampleCount(desc.sampleCount);
return pso;
} }
RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) { RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) {

View File

@@ -1,63 +1,204 @@
#include "XCEngine/RHI/D3D12/D3D12PipelineState.h" #include "XCEngine/RHI/D3D12/D3D12PipelineState.h"
#include <cstring>
namespace XCEngine { namespace XCEngine {
namespace RHI { namespace RHI {
D3D12PipelineState::D3D12PipelineState() { D3D12PipelineState::D3D12PipelineState(ID3D12Device* device)
: m_device(device), m_finalized(false) {
m_renderTargetFormats[0] = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
m_depthStencilFormat = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
}
bool D3D12PipelineState::Initialize(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC& desc) {
m_device = device;
m_rootSignature = desc.pRootSignature;
m_rasterizerDesc.fillMode = static_cast<uint32_t>(desc.RasterizerState.FillMode);
m_rasterizerDesc.cullMode = static_cast<uint32_t>(desc.RasterizerState.CullMode);
m_rasterizerDesc.frontFace = desc.RasterizerState.FrontCounterClockwise ? 1 : 0; // 1 = CounterClockwise
m_rasterizerDesc.depthClipEnable = desc.RasterizerState.DepthClipEnable != 0;
m_blendDesc.blendEnable = desc.BlendState.RenderTarget[0].BlendEnable != 0;
m_blendDesc.srcBlend = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].SrcBlend);
m_blendDesc.dstBlend = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].DestBlend);
m_blendDesc.blendOp = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].BlendOp);
m_blendDesc.srcBlendAlpha = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].SrcBlendAlpha);
m_blendDesc.dstBlendAlpha = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].DestBlendAlpha);
m_blendDesc.blendOpAlpha = static_cast<uint32_t>(desc.BlendState.RenderTarget[0].BlendOpAlpha);
m_blendDesc.colorWriteMask = desc.BlendState.RenderTarget[0].RenderTargetWriteMask;
m_depthStencilDesc.depthTestEnable = desc.DepthStencilState.DepthEnable != 0;
m_depthStencilDesc.depthWriteEnable = (desc.DepthStencilState.DepthWriteMask == D3D12_DEPTH_WRITE_MASK_ALL);
m_depthStencilDesc.depthFunc = static_cast<uint32_t>(desc.DepthStencilState.DepthFunc);
m_depthStencilDesc.stencilEnable = desc.DepthStencilState.StencilEnable != 0;
m_depthStencilDesc.stencilReadMask = desc.DepthStencilState.StencilReadMask;
m_depthStencilDesc.stencilWriteMask = desc.DepthStencilState.StencilWriteMask;
m_topologyType = static_cast<uint32_t>(desc.PrimitiveTopologyType);
m_renderTargetCount = desc.NumRenderTargets;
for (UINT i = 0; i < desc.NumRenderTargets; ++i) {
m_renderTargetFormats[i] = static_cast<uint32_t>(desc.RTVFormats[i]);
}
m_depthStencilFormat = static_cast<uint32_t>(desc.DSVFormat);
m_sampleCount = desc.SampleDesc.Count;
// Set shader bytecodes
m_vsBytecode = desc.VS;
m_psBytecode = desc.PS;
m_gsBytecode = desc.GS;
// Set input layout
m_inputElements.clear();
for (UINT i = 0; i < desc.InputLayout.NumElements; ++i) {
m_inputElements.push_back(desc.InputLayout.pInputElementDescs[i]);
}
return Finalize();
} }
D3D12PipelineState::~D3D12PipelineState() { D3D12PipelineState::~D3D12PipelineState() {
Shutdown(); Shutdown();
} }
bool D3D12PipelineState::Initialize(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC& desc) { void D3D12PipelineState::SetInputLayout(const InputLayoutDesc& layout) {
HRESULT hResult = device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&m_pipelineState)); m_inputLayoutDesc = layout;
if (FAILED(hResult)) { m_inputElements.clear();
for (const auto& elem : layout.elements) {
D3D12_INPUT_ELEMENT_DESC desc = {};
desc.SemanticName = elem.semanticName.c_str();
desc.SemanticIndex = elem.semanticIndex;
desc.Format = ToD3D12(static_cast<Format>(elem.format));
desc.InputSlot = elem.inputSlot;
desc.AlignedByteOffset = elem.alignedByteOffset;
desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
desc.InstanceDataStepRate = 0;
m_inputElements.push_back(desc);
}
}
void D3D12PipelineState::SetRasterizerState(const RasterizerDesc& state) {
m_rasterizerDesc = state;
}
void D3D12PipelineState::SetBlendState(const BlendDesc& state) {
m_blendDesc = state;
}
void D3D12PipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) {
m_depthStencilDesc = state;
}
void D3D12PipelineState::SetTopology(uint32_t topologyType) {
m_topologyType = topologyType;
}
void D3D12PipelineState::SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) {
m_renderTargetCount = count;
for (uint32_t i = 0; i < count && i < 8; ++i) {
m_renderTargetFormats[i] = formats[i];
}
m_depthStencilFormat = depthFormat;
}
void D3D12PipelineState::SetSampleCount(uint32_t count) {
m_sampleCount = count;
}
PipelineStateHash D3D12PipelineState::GetHash() const {
PipelineStateHash hash = {};
hash.blendStateHash = std::hash<uint64_t>{}(*reinterpret_cast<const uint64_t*>(&m_blendDesc));
hash.depthStateHash = std::hash<uint64_t>{}(*reinterpret_cast<const uint64_t*>(&m_depthStencilDesc));
hash.rasterizerStateHash = std::hash<uint64_t>{}(*reinterpret_cast<const uint64_t*>(&m_rasterizerDesc));
hash.topologyHash = m_topologyType;
hash.renderTargetHash = m_renderTargetCount | (m_depthStencilFormat << 8);
return hash;
}
void D3D12PipelineState::SetShaderBytecodes(const D3D12_SHADER_BYTECODE& vs, const D3D12_SHADER_BYTECODE& ps, const D3D12_SHADER_BYTECODE& gs) {
m_vsBytecode = vs;
m_psBytecode = ps;
m_gsBytecode = gs;
}
bool D3D12PipelineState::Finalize() {
if (m_finalized) return true;
return CreateD3D12PSO();
}
bool D3D12PipelineState::CreateD3D12PSO() {
if (!m_vsBytecode.pShaderBytecode || !m_psBytecode.pShaderBytecode) {
return false; return false;
} }
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
desc.pRootSignature = m_rootSignature;
desc.VS = m_vsBytecode;
desc.PS = m_psBytecode;
desc.GS = m_gsBytecode;
desc.InputLayout.NumElements = static_cast<UINT>(m_inputElements.size());
desc.InputLayout.pInputElementDescs = m_inputElements.data();
desc.RasterizerState.FillMode = static_cast<D3D12_FILL_MODE>(m_rasterizerDesc.fillMode);
desc.RasterizerState.CullMode = static_cast<D3D12_CULL_MODE>(m_rasterizerDesc.cullMode);
desc.RasterizerState.FrontCounterClockwise = (m_rasterizerDesc.frontFace != 0);
desc.RasterizerState.DepthClipEnable = m_rasterizerDesc.depthClipEnable;
desc.RasterizerState.MultisampleEnable = m_rasterizerDesc.multisampleEnable;
desc.RasterizerState.AntialiasedLineEnable = m_rasterizerDesc.antialiasedLineEnable;
desc.BlendState.RenderTarget[0].BlendEnable = m_blendDesc.blendEnable;
desc.BlendState.RenderTarget[0].SrcBlend = static_cast<D3D12_BLEND>(m_blendDesc.srcBlend);
desc.BlendState.RenderTarget[0].DestBlend = static_cast<D3D12_BLEND>(m_blendDesc.dstBlend);
desc.BlendState.RenderTarget[0].BlendOp = static_cast<D3D12_BLEND_OP>(m_blendDesc.blendOp);
desc.BlendState.RenderTarget[0].SrcBlendAlpha = static_cast<D3D12_BLEND>(m_blendDesc.srcBlendAlpha);
desc.BlendState.RenderTarget[0].DestBlendAlpha = static_cast<D3D12_BLEND>(m_blendDesc.dstBlendAlpha);
desc.BlendState.RenderTarget[0].BlendOpAlpha = static_cast<D3D12_BLEND_OP>(m_blendDesc.blendOpAlpha);
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = m_blendDesc.colorWriteMask;
desc.DepthStencilState.DepthEnable = m_depthStencilDesc.depthTestEnable;
desc.DepthStencilState.DepthWriteMask = m_depthStencilDesc.depthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
desc.DepthStencilState.DepthFunc = static_cast<D3D12_COMPARISON_FUNC>(m_depthStencilDesc.depthFunc);
desc.DepthStencilState.StencilEnable = m_depthStencilDesc.stencilEnable;
desc.DepthStencilState.StencilReadMask = m_depthStencilDesc.stencilReadMask;
desc.DepthStencilState.StencilWriteMask = m_depthStencilDesc.stencilWriteMask;
desc.DepthStencilState.FrontFace.StencilFailOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.front.failOp);
desc.DepthStencilState.FrontFace.StencilPassOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.front.passOp);
desc.DepthStencilState.FrontFace.StencilDepthFailOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.front.depthFailOp);
desc.DepthStencilState.FrontFace.StencilFunc = static_cast<D3D12_COMPARISON_FUNC>(m_depthStencilDesc.front.func);
desc.DepthStencilState.BackFace.StencilFailOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.back.failOp);
desc.DepthStencilState.BackFace.StencilPassOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.back.passOp);
desc.DepthStencilState.BackFace.StencilDepthFailOp = static_cast<D3D12_STENCIL_OP>(m_depthStencilDesc.back.depthFailOp);
desc.DepthStencilState.BackFace.StencilFunc = static_cast<D3D12_COMPARISON_FUNC>(m_depthStencilDesc.back.func);
desc.NumRenderTargets = m_renderTargetCount;
for (uint32_t i = 0; i < m_renderTargetCount && i < 8; ++i) {
desc.RTVFormats[i] = static_cast<DXGI_FORMAT>(m_renderTargetFormats[i]);
}
desc.DSVFormat = static_cast<DXGI_FORMAT>(m_depthStencilFormat);
desc.SampleDesc.Count = m_sampleCount;
desc.SampleDesc.Quality = 0;
desc.SampleMask = 0xffffffff;
desc.PrimitiveTopologyType = static_cast<D3D12_PRIMITIVE_TOPOLOGY_TYPE>(m_topologyType);
HRESULT hr = m_device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&m_pipelineState));
if (FAILED(hr)) {
return false;
}
m_finalized = true;
return true; return true;
} }
void D3D12PipelineState::Shutdown() { void D3D12PipelineState::Shutdown() {
m_pipelineState.Reset(); m_pipelineState.Reset();
m_finalized = false;
} }
D3D12_GRAPHICS_PIPELINE_STATE_DESC D3D12PipelineState::CreateDesc( void D3D12PipelineState::Bind() {
ID3D12RootSignature* rootSignature, }
const D3D12_SHADER_BYTECODE& vs,
const D3D12_SHADER_BYTECODE& ps, void D3D12PipelineState::Unbind() {
const D3D12_SHADER_BYTECODE& gs,
uint32_t inputElementCount,
const D3D12_INPUT_ELEMENT_DESC* inputElements) {
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
desc.pRootSignature = rootSignature;
desc.VS = vs;
desc.PS = ps;
desc.GS = gs;
desc.InputLayout.NumElements = inputElementCount;
desc.InputLayout.pInputElementDescs = inputElements;
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.SampleMask = 0xffffffff;
desc.NumRenderTargets = 1;
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
desc.RasterizerState.DepthClipEnable = TRUE;
desc.DepthStencilState.DepthEnable = TRUE;
desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
desc.BlendState.RenderTarget[0].BlendEnable = FALSE;
desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE;
desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO;
desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
return desc;
} }
D3D12_INPUT_ELEMENT_DESC D3D12PipelineState::CreateInputElement( D3D12_INPUT_ELEMENT_DESC D3D12PipelineState::CreateInputElement(
@@ -85,11 +226,5 @@ D3D12_INPUT_ELEMENT_DESC D3D12PipelineState::CreateInputElement(
return CreateInputElement(semanticName, semanticIndex, format, inputSlot, D3D12_APPEND_ALIGNED_ELEMENT); return CreateInputElement(semanticName, semanticIndex, format, inputSlot, D3D12_APPEND_ALIGNED_ELEMENT);
} }
void D3D12PipelineState::Bind() {
}
void D3D12PipelineState::Unbind() {
}
} // namespace RHI } // namespace RHI
} // namespace XCEngine } // namespace XCEngine

View File

@@ -444,8 +444,15 @@ RHIShader* OpenGLDevice::CompileShader(const ShaderCompileDesc& desc) {
return shader; return shader;
} }
RHIPipelineState* OpenGLDevice::CreatePipelineState(const PipelineStateDesc& desc) { RHIPipelineState* OpenGLDevice::CreatePipelineState(const GraphicsPipelineDesc& desc) {
auto* pso = new OpenGLPipelineState(); auto* pso = new OpenGLPipelineState();
pso->SetInputLayout(desc.inputLayout);
pso->SetRasterizerState(desc.rasterizerState);
pso->SetBlendState(desc.blendState);
pso->SetDepthStencilState(desc.depthStencilState);
pso->SetTopology(desc.topologyType);
pso->SetRenderTargetFormats(desc.renderTargetCount, desc.renderTargetFormats, desc.depthStencilFormat);
pso->SetSampleCount(desc.sampleCount);
return pso; return pso;
} }

View File

@@ -1,154 +1,90 @@
#define GLFW_INCLUDE_NONE
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
#include <glad/glad.h> #include <glad/glad.h>
namespace XCEngine { namespace XCEngine {
namespace RHI { namespace RHI {
static unsigned int ToGLComparisonFunc(ComparisonFunc func) {
switch (func) {
case ComparisonFunc::Never: return GL_NEVER;
case ComparisonFunc::Less: return GL_LESS;
case ComparisonFunc::Equal: return GL_EQUAL;
case ComparisonFunc::LessEqual: return GL_LEQUAL;
case ComparisonFunc::Greater: return GL_GREATER;
case ComparisonFunc::NotEqual: return GL_NOTEQUAL;
case ComparisonFunc::GreaterEqual: return GL_GEQUAL;
case ComparisonFunc::Always: return GL_ALWAYS;
default: return GL_LESS;
}
}
static unsigned int ToGLBlendFactor(BlendFactor factor) {
switch (factor) {
case BlendFactor::Zero: return GL_ZERO;
case BlendFactor::One: return GL_ONE;
case BlendFactor::SrcColor: return GL_SRC_COLOR;
case BlendFactor::InvSrcColor: return GL_ONE_MINUS_SRC_COLOR;
case BlendFactor::DstColor: return GL_DST_COLOR;
case BlendFactor::InvDstColor: return GL_ONE_MINUS_DST_COLOR;
case BlendFactor::SrcAlpha: return GL_SRC_ALPHA;
case BlendFactor::InvSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
case BlendFactor::DstAlpha: return GL_DST_ALPHA;
case BlendFactor::InvDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
case BlendFactor::SrcAlphaSat: return GL_SRC_ALPHA_SATURATE;
case BlendFactor::Src1Color: return GL_SRC1_COLOR;
case BlendFactor::InvSrc1Color: return GL_ONE_MINUS_SRC1_COLOR;
case BlendFactor::Src1Alpha: return GL_SRC1_ALPHA;
case BlendFactor::InvSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA;
default: return GL_ONE;
}
}
static unsigned int ToGLBlendOp(BlendOp op) {
switch (op) {
case BlendOp::Add: return GL_FUNC_ADD;
case BlendOp::Subtract: return GL_FUNC_SUBTRACT;
case BlendOp::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT;
case BlendOp::Min: return GL_MIN;
case BlendOp::Max: return GL_MAX;
default: return GL_FUNC_ADD;
}
}
static unsigned int ToGLCullFace(CullFace face) {
switch (face) {
case CullFace::Front: return GL_FRONT;
case CullFace::Back: return GL_BACK;
case CullFace::FrontAndBack: return GL_FRONT_AND_BACK;
default: return GL_BACK;
}
}
static unsigned int ToGLFrontFace(FrontFace face) {
switch (face) {
case FrontFace::Clockwise: return GL_CW;
case FrontFace::CounterClockwise: return GL_CCW;
default: return GL_CCW;
}
}
static unsigned int ToGLPolygonMode(PolygonMode mode) {
switch (mode) {
case PolygonMode::Point: return GL_POINT;
case PolygonMode::Line: return GL_LINE;
case PolygonMode::Fill: return GL_FILL;
default: return GL_FILL;
}
}
static unsigned int ToGLStencilOp(StencilOp op) {
switch (op) {
case StencilOp::Keep: return GL_KEEP;
case StencilOp::Zero: return GL_ZERO;
case StencilOp::Replace: return GL_REPLACE;
case StencilOp::Incr: return GL_INCR;
case StencilOp::IncrSat: return GL_INCR_WRAP;
case StencilOp::Decr: return GL_DECR;
case StencilOp::DecrSat: return GL_DECR_WRAP;
case StencilOp::Invert: return GL_INVERT;
default: return GL_KEEP;
}
}
OpenGLPipelineState::OpenGLPipelineState() OpenGLPipelineState::OpenGLPipelineState()
: m_program(0) : m_program(0), m_programAttached(false) {
, m_programAttached(false) {
m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0.0f;
} }
OpenGLPipelineState::~OpenGLPipelineState() { OpenGLPipelineState::~OpenGLPipelineState() {
} }
void OpenGLPipelineState::SetDepthStencilState(const OpenGLDepthStencilState& state) { void OpenGLPipelineState::SetInputLayout(const InputLayoutDesc& layout) {
m_depthStencilState = state; m_inputLayoutDesc = layout;
} }
void OpenGLPipelineState::SetBlendState(const OpenGLBlendState& state) { void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) {
m_blendState = state; m_rasterizerDesc = state;
} }
void OpenGLPipelineState::SetRasterizerState(const OpenGLRasterizerState& state) { void OpenGLPipelineState::SetBlendState(const BlendDesc& state) {
m_rasterizerState = state; m_blendDesc = state;
} }
void OpenGLPipelineState::SetViewport(const ViewportState& state) { void OpenGLPipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) {
m_viewportState = state; m_depthStencilDesc = state;
} }
void OpenGLPipelineState::SetScissor(const ScissorState& state) { void OpenGLPipelineState::SetTopology(uint32_t topologyType) {
m_scissorState = state; m_topologyType = topologyType;
} }
void OpenGLPipelineState::SetLogicalOperation(const LogicalOperation& state) { void OpenGLPipelineState::SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) {
m_logicalOperation = state; }
void OpenGLPipelineState::SetSampleCount(uint32_t count) {
}
PipelineStateHash OpenGLPipelineState::GetHash() const {
PipelineStateHash hash = {};
return hash;
}
void OpenGLPipelineState::Shutdown() {
m_program = 0;
m_programAttached = false;
}
void OpenGLPipelineState::Bind() {
if (m_programAttached) {
glUseProgram(m_program);
}
Apply();
}
void OpenGLPipelineState::Unbind() {
glUseProgram(0);
} }
void OpenGLPipelineState::Apply() { void OpenGLPipelineState::Apply() {
ApplyDepthStencil(); ApplyDepthStencil();
ApplyBlend(); ApplyBlend();
ApplyRasterizer(); ApplyRasterizer();
ApplyViewport();
ApplyScissor();
} }
void OpenGLPipelineState::ApplyDepthStencil() { void OpenGLPipelineState::ApplyDepthStencil() {
if (m_depthStencilState.depthTestEnable) { if (m_glDepthStencilState.depthTestEnable) {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
} else { } else {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
glDepthMask(m_depthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); glDepthMask(m_glDepthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE);
glDepthFunc(ToGLComparisonFunc(m_depthStencilState.depthFunc)); glDepthFunc(static_cast<GLenum>(m_glDepthStencilState.depthFunc));
if (m_depthStencilState.stencilEnable) { if (m_glDepthStencilState.stencilEnable) {
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilMask(m_depthStencilState.stencilWriteMask); glStencilMask(m_glDepthStencilState.stencilWriteMask);
glStencilFunc(ToGLComparisonFunc(m_depthStencilState.stencilFunc), m_depthStencilState.stencilRef, m_depthStencilState.stencilReadMask); glStencilFunc(
static_cast<GLenum>(m_glDepthStencilState.stencilFunc),
m_glDepthStencilState.stencilRef,
m_glDepthStencilState.stencilReadMask
);
glStencilOp( glStencilOp(
ToGLStencilOp(m_depthStencilState.stencilFailOp), static_cast<GLenum>(m_glDepthStencilState.stencilFailOp),
ToGLStencilOp(m_depthStencilState.stencilDepthFailOp), static_cast<GLenum>(m_glDepthStencilState.stencilDepthFailOp),
ToGLStencilOp(m_depthStencilState.stencilDepthPassOp) static_cast<GLenum>(m_glDepthStencilState.stencilDepthPassOp)
); );
} else { } else {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
@@ -156,29 +92,23 @@ void OpenGLPipelineState::ApplyDepthStencil() {
} }
void OpenGLPipelineState::ApplyBlend() { void OpenGLPipelineState::ApplyBlend() {
if (m_blendState.blendEnable) { if (m_glBlendState.blendEnable) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFuncSeparate( glBlendFuncSeparate(
ToGLBlendFactor(m_blendState.srcBlend), static_cast<GLenum>(m_glBlendState.srcBlend),
ToGLBlendFactor(m_blendState.dstBlend), static_cast<GLenum>(m_glBlendState.dstBlend),
ToGLBlendFactor(m_blendState.srcBlendAlpha), static_cast<GLenum>(m_glBlendState.srcBlendAlpha),
ToGLBlendFactor(m_blendState.dstBlendAlpha) static_cast<GLenum>(m_glBlendState.dstBlendAlpha)
); );
glBlendEquationSeparate( glBlendEquationSeparate(
ToGLBlendOp(m_blendState.blendOp), static_cast<GLenum>(m_glBlendState.blendOp),
ToGLBlendOp(m_blendState.blendOpAlpha) static_cast<GLenum>(m_glBlendState.blendOpAlpha)
);
glBlendColor(
m_blendState.blendFactor[0],
m_blendState.blendFactor[1],
m_blendState.blendFactor[2],
m_blendState.blendFactor[3]
); );
glColorMask( glColorMask(
(m_blendState.colorWriteMask & 1) != 0, (m_glBlendState.colorWriteMask & 1) != 0,
(m_blendState.colorWriteMask & 2) != 0, (m_glBlendState.colorWriteMask & 2) != 0,
(m_blendState.colorWriteMask & 4) != 0, (m_glBlendState.colorWriteMask & 4) != 0,
(m_blendState.colorWriteMask & 8) != 0 (m_glBlendState.colorWriteMask & 8) != 0
); );
} else { } else {
glDisable(GL_BLEND); glDisable(GL_BLEND);
@@ -186,40 +116,21 @@ void OpenGLPipelineState::ApplyBlend() {
} }
void OpenGLPipelineState::ApplyRasterizer() { void OpenGLPipelineState::ApplyRasterizer() {
if (m_rasterizerState.cullFaceEnable) { if (m_glRasterizerState.cullFaceEnable) {
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(ToGLCullFace(m_rasterizerState.cullFace)); glCullFace(static_cast<GLenum>(m_glRasterizerState.cullFace));
glFrontFace(ToGLFrontFace(m_rasterizerState.frontFace)); glFrontFace(static_cast<GLenum>(m_glRasterizerState.frontFace));
} else { } else {
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }
glPolygonMode(GL_FRONT_AND_BACK, ToGLPolygonMode(m_rasterizerState.polygonMode)); glPolygonMode(GL_FRONT_AND_BACK, static_cast<GLenum>(m_glRasterizerState.polygonMode));
if (m_rasterizerState.polygonOffsetFactor != 0.0f || m_rasterizerState.polygonOffsetUnits != 0.0f) { if (m_glRasterizerState.multisampleEnable) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(m_rasterizerState.polygonOffsetFactor, m_rasterizerState.polygonOffsetUnits);
} else {
glDisable(GL_POLYGON_OFFSET_FILL);
}
if (m_rasterizerState.scissorTestEnable) {
glEnable(GL_SCISSOR_TEST);
} else {
glDisable(GL_SCISSOR_TEST);
}
if (m_rasterizerState.multisampleEnable) {
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
} else { } else {
glDisable(GL_MULTISAMPLE); glDisable(GL_MULTISAMPLE);
} }
if (m_rasterizerState.sampleAlphaToCoverageEnable) {
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
} else {
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
} }
void OpenGLPipelineState::ApplyViewport() { void OpenGLPipelineState::ApplyViewport() {
@@ -237,6 +148,31 @@ void OpenGLPipelineState::ApplyScissor() {
} }
} }
void OpenGLPipelineState::SetProgram(unsigned int program) {
m_program = program;
m_programAttached = (program != 0);
}
void OpenGLPipelineState::SetDepthStencilState(const OpenGLDepthStencilState& state) {
m_glDepthStencilState = state;
}
void OpenGLPipelineState::SetBlendState(const OpenGLBlendState& state) {
m_glBlendState = state;
}
void OpenGLPipelineState::SetRasterizerState(const OpenGLRasterizerState& state) {
m_glRasterizerState = state;
}
void OpenGLPipelineState::SetViewport(const ViewportState& state) {
m_viewportState = state;
}
void OpenGLPipelineState::SetScissor(const ScissorState& state) {
m_scissorState = state;
}
void OpenGLPipelineState::SetClearColor(float r, float g, float b, float a) { void OpenGLPipelineState::SetClearColor(float r, float g, float b, float a) {
m_clearColor[0] = r; m_clearColor[0] = r;
m_clearColor[1] = g; m_clearColor[1] = g;
@@ -265,24 +201,16 @@ void OpenGLPipelineState::DetachShader() {
glUseProgram(0); glUseProgram(0);
} }
void OpenGLPipelineState::Shutdown() { const OpenGLDepthStencilState& OpenGLPipelineState::GetOpenGLDepthStencilState() const {
m_program = 0; return m_glDepthStencilState;
m_programAttached = false;
} }
void OpenGLPipelineState::Bind() { const OpenGLBlendState& OpenGLPipelineState::GetOpenGLBlendState() const {
if (m_programAttached) { return m_glBlendState;
glUseProgram(m_program);
}
Apply();
} }
void OpenGLPipelineState::Unbind() { const OpenGLRasterizerState& OpenGLPipelineState::GetOpenGLRasterizerState() const {
glUseProgram(0); return m_glRasterizerState;
}
void* OpenGLPipelineState::GetNativeHandle() {
return reinterpret_cast<void*>(static_cast<uintptr_t>(m_program));
} }
} // namespace RHI } // namespace RHI