diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h index af76538c..6d62c676 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h @@ -158,11 +158,16 @@ public: void PopDebugGroup(); void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) override; + void SetPrimitiveTopology(PrimitiveTopology topology) override; void SetViewport(const Viewport& viewport) override; void SetViewports(uint32_t count, const Viewport* viewports) override; void SetScissorRect(const Rect& rect) override; void SetScissorRects(uint32_t count, const Rect* rects) override; void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) override; + void SetDepthStencilState(const DepthStencilState& state) override; + void SetStencilRef(uint8_t ref) override; + void SetBlendState(const BlendState& state) override; + void SetBlendFactor(const float factor[4]) override; void ClearRenderTarget(void* renderTarget, const float color[4]) override; void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) override; void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) override; diff --git a/engine/include/XCEngine/RHI/RHICommandList.h b/engine/include/XCEngine/RHI/RHICommandList.h index ae810774..d3c3533f 100644 --- a/engine/include/XCEngine/RHI/RHICommandList.h +++ b/engine/include/XCEngine/RHI/RHICommandList.h @@ -6,6 +6,40 @@ namespace XCEngine { namespace RHI { +struct DepthStencilState { + bool depthEnable = true; + bool depthWriteMask = true; + ComparisonFunc depthFunc = ComparisonFunc::Less; + bool stencilEnable = false; + uint8_t stencilReadMask = 0xFF; + uint8_t stencilWriteMask = 0xFF; + struct StencilOpDesc { + StencilOp stencilFailOp = StencilOp::Keep; + StencilOp stencilDepthFailOp = StencilOp::Keep; + StencilOp stencilPassOp = StencilOp::Keep; + ComparisonFunc stencilFunc = ComparisonFunc::Always; + }; + StencilOpDesc frontFace; + StencilOpDesc backFace; +}; + +struct BlendState { + bool alphaToCoverageEnable = false; + bool independentBlendEnable = false; + struct RenderTarget { + bool blendEnable = false; + BlendFactor srcBlend = BlendFactor::One; + BlendFactor dstBlend = BlendFactor::Zero; + BlendOp blendOp = BlendOp::Add; + BlendFactor srcBlendAlpha = BlendFactor::One; + BlendFactor dstBlendAlpha = BlendFactor::Zero; + BlendOp blendOpAlpha = BlendOp::Add; + uint8_t renderTargetWriteMask = 0xF; + }; + RenderTarget renderTargets[8]; + float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; +}; + class RHICommandList { public: virtual ~RHICommandList() = default; @@ -18,12 +52,18 @@ public: virtual void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0; virtual void SetPipelineState(void* pso) = 0; + virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 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 SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) = 0; + virtual void SetDepthStencilState(const DepthStencilState& state) = 0; + virtual void SetStencilRef(uint8_t ref) = 0; + virtual void SetBlendState(const BlendState& state) = 0; + virtual void SetBlendFactor(const float factor[4]) = 0; + virtual void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) = 0; virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) = 0; virtual void SetIndexBuffer(void* buffer, uint64_t offset, Format format) = 0; diff --git a/engine/src/RHI/D3D12/D3D12CommandList.cpp b/engine/src/RHI/D3D12/D3D12CommandList.cpp index 6b80a422..d82d1adf 100644 --- a/engine/src/RHI/D3D12/D3D12CommandList.cpp +++ b/engine/src/RHI/D3D12/D3D12CommandList.cpp @@ -256,10 +256,6 @@ void D3D12CommandList::SetStencilRef(uint32_t stencilRef) { m_commandList->OMSetStencilRef(stencilRef); } -void D3D12CommandList::SetBlendFactor(const float blendFactor[4]) { - m_commandList->OMSetBlendFactor(blendFactor); -} - void D3D12CommandList::SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) { } diff --git a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp index dc2b2835..ecf446e5 100644 --- a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp +++ b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp @@ -522,5 +522,143 @@ void OpenGLCommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount, reinterpret_cast(startIndex * sizeof(GLuint)), static_cast(instanceCount)); } +static unsigned int ToGLPrimitiveTopology(PrimitiveTopology topology) { + switch (topology) { + case PrimitiveTopology::PointList: return GL_POINTS; + case PrimitiveTopology::LineList: return GL_LINES; + case PrimitiveTopology::LineStrip: return GL_LINE_STRIP; + case PrimitiveTopology::TriangleList: return GL_TRIANGLES; + case PrimitiveTopology::TriangleStrip: return GL_TRIANGLE_STRIP; + case PrimitiveTopology::LineListAdj: return GL_LINES_ADJACENCY; + case PrimitiveTopology::LineStripAdj: return GL_LINE_STRIP_ADJACENCY; + case PrimitiveTopology::TriangleListAdj: return GL_TRIANGLES_ADJACENCY; + case PrimitiveTopology::TriangleStripAdj: return GL_TRIANGLE_STRIP_ADJACENCY; + case PrimitiveTopology::PatchList: return GL_PATCHES; + default: return GL_TRIANGLES; + } +} + +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 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::IncrSat: return GL_INCR; + case StencilOp::DecrSat: return GL_DECR; + case StencilOp::Invert: return GL_INVERT; + case StencilOp::Incr: return GL_INCR_WRAP; + case StencilOp::Decr: return GL_DECR_WRAP; + default: return GL_KEEP; + } +} + +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::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::DstColor: return GL_DST_COLOR; + case BlendFactor::InvDstColor: return GL_ONE_MINUS_DST_COLOR; + case BlendFactor::SrcAlphaSat: return GL_SRC_ALPHA_SATURATE; + case BlendFactor::BlendFactor: return GL_CONSTANT_COLOR; + case BlendFactor::InvBlendFactor: return GL_ONE_MINUS_CONSTANT_COLOR; + 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; + } +} + +void OpenGLCommandList::SetPrimitiveTopology(PrimitiveTopology topology) { + m_primitiveType = ToGLPrimitiveTopology(topology); +} + +void OpenGLCommandList::SetDepthStencilState(const DepthStencilState& state) { + if (state.depthEnable) { + glEnable(GL_DEPTH_TEST); + glDepthFunc(ToGLComparisonFunc(state.depthFunc)); + glDepthMask(state.depthWriteMask ? GL_TRUE : GL_FALSE); + } else { + glDisable(GL_DEPTH_TEST); + } + + if (state.stencilEnable) { + glEnable(GL_STENCIL_TEST); + glStencilMask(state.stencilWriteMask); + glStencilFunc(ToGLComparisonFunc(state.frontFace.stencilFunc), 0, state.stencilReadMask); + glStencilOp( + ToGLStencilOp(state.frontFace.stencilFailOp), + ToGLStencilOp(state.frontFace.stencilDepthFailOp), + ToGLStencilOp(state.frontFace.stencilPassOp) + ); + } else { + glDisable(GL_STENCIL_TEST); + } +} + +void OpenGLCommandList::SetStencilRef(uint8_t ref) { + glStencilFunc(GL_FRONT_AND_BACK, ref, 0xFF); +} + +void OpenGLCommandList::SetBlendState(const BlendState& state) { + if (state.alphaToCoverageEnable) { + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } else { + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + + const auto& rt = state.renderTargets[0]; + if (rt.blendEnable) { + glEnable(GL_BLEND); + glBlendFuncSeparate( + ToGLBlendFactor(rt.srcBlend), + ToGLBlendFactor(rt.dstBlend), + ToGLBlendFactor(rt.srcBlendAlpha), + ToGLBlendFactor(rt.dstBlendAlpha) + ); + glBlendEquationSeparate( + ToGLBlendOp(rt.blendOp), + ToGLBlendOp(rt.blendOpAlpha) + ); + } else { + glDisable(GL_BLEND); + } +} + +void OpenGLCommandList::SetBlendFactor(const float factor[4]) { + glBlendColor(factor[0], factor[1], factor[2], factor[3]); +} + } // namespace RHI } // namespace XCEngine