feat(RHI): add rendering state abstraction to RHICommandList
- Add DepthStencilState and BlendState structs to RHICommandList - Add SetPrimitiveTopology, SetDepthStencilState, SetStencilRef, SetBlendState, SetBlendFactor virtual methods - Implement new methods in OpenGL backend with full state control - Implement stub methods in D3D12 backend (states controlled via PSO)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
|
||||
@@ -522,5 +522,143 @@ void OpenGLCommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount,
|
||||
reinterpret_cast<const void*>(startIndex * sizeof(GLuint)), static_cast<GLsizei>(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
|
||||
|
||||
Reference in New Issue
Block a user