#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include "XCEngine/RHI/OpenGL/OpenGLShader.h" #include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include #include namespace XCEngine { namespace RHI { OpenGLPipelineState::OpenGLPipelineState() : m_program(0), m_programAttached(false) { } OpenGLPipelineState::~OpenGLPipelineState() { } void OpenGLPipelineState::SetInputLayout(const InputLayoutDesc& layout) { m_inputLayoutDesc = layout; } void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) { m_rasterizerDesc = state; m_glRasterizerState.cullFaceEnable = static_cast(state.cullMode) != CullMode::None; m_glRasterizerState.cullFace = static_cast(state.cullMode); m_glRasterizerState.frontFace = static_cast(state.frontFace); m_glRasterizerState.polygonMode = static_cast(state.fillMode); m_glRasterizerState.depthClipEnable = state.depthClipEnable; m_glRasterizerState.scissorTestEnable = state.scissorTestEnable; m_glRasterizerState.multisampleEnable = state.multisampleEnable; m_glRasterizerState.polygonOffsetFactor = state.slopeScaledDepthBias; m_glRasterizerState.polygonOffsetUnits = static_cast(state.depthBias); } void OpenGLPipelineState::SetBlendState(const BlendDesc& state) { m_blendDesc = state; m_glBlendState.blendEnable = state.blendEnable; m_glBlendState.srcBlend = static_cast(state.srcBlend); m_glBlendState.dstBlend = static_cast(state.dstBlend); m_glBlendState.srcBlendAlpha = static_cast(state.srcBlendAlpha); m_glBlendState.dstBlendAlpha = static_cast(state.dstBlendAlpha); m_glBlendState.blendOp = static_cast(state.blendOp); m_glBlendState.blendOpAlpha = static_cast(state.blendOpAlpha); m_glBlendState.colorWriteMask = state.colorWriteMask; std::memcpy(m_glBlendState.blendFactor, state.blendFactor, sizeof(state.blendFactor)); } void OpenGLPipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) { m_depthStencilDesc = state; m_glDepthStencilState.depthTestEnable = state.depthTestEnable; m_glDepthStencilState.depthWriteEnable = state.depthWriteEnable; m_glDepthStencilState.depthFunc = static_cast(state.depthFunc); m_glDepthStencilState.stencilEnable = state.stencilEnable; m_glDepthStencilState.stencilReadMask = state.stencilReadMask; m_glDepthStencilState.stencilWriteMask = state.stencilWriteMask; m_glDepthStencilState.frontStencilFunc = static_cast(state.front.func); m_glDepthStencilState.frontStencilFailOp = static_cast(state.front.failOp); m_glDepthStencilState.frontStencilDepthFailOp = static_cast(state.front.depthFailOp); m_glDepthStencilState.frontStencilDepthPassOp = static_cast(state.front.passOp); m_glDepthStencilState.backStencilFunc = static_cast(state.back.func); m_glDepthStencilState.backStencilFailOp = static_cast(state.back.failOp); m_glDepthStencilState.backStencilDepthFailOp = static_cast(state.back.depthFailOp); m_glDepthStencilState.backStencilDepthPassOp = static_cast(state.back.passOp); } void OpenGLPipelineState::SetTopology(uint32_t topologyType) { m_topologyType = topologyType; } void OpenGLPipelineState::SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) { } void OpenGLPipelineState::SetSampleCount(uint32_t count) { } void OpenGLPipelineState::SetComputeShader(RHIShader* shader) { m_computeShader = shader; if (shader) { OpenGLShader* glShader = static_cast(shader); m_computeProgram = glShader->GetID(); } else { m_computeProgram = 0; } } PipelineStateHash OpenGLPipelineState::GetHash() const { PipelineStateHash hash = {}; return hash; } void OpenGLPipelineState::Shutdown() { m_graphicsShader.reset(); m_program = 0; m_computeProgram = 0; m_computeShader = nullptr; m_programAttached = false; } void OpenGLPipelineState::Bind() { if (HasComputeShader()) { glUseProgram(m_computeProgram); } else if (m_programAttached && m_program != 0) { glUseProgram(m_program); } Apply(); } void OpenGLPipelineState::Unbind() { glUseProgram(0); } void OpenGLPipelineState::Apply() { ApplyDepthStencil(); ApplyBlend(); ApplyRasterizer(); } void OpenGLPipelineState::ApplyDepthStencil() { if (m_glDepthStencilState.depthTestEnable) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } glDepthMask(m_glDepthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); glDepthFunc(ToOpenGL(m_glDepthStencilState.depthFunc)); if (m_glDepthStencilState.stencilEnable) { glEnable(GL_STENCIL_TEST); glStencilMaskSeparate(GL_FRONT, m_glDepthStencilState.stencilWriteMask); glStencilMaskSeparate(GL_BACK, m_glDepthStencilState.stencilWriteMask); glStencilFuncSeparate( GL_FRONT, ToOpenGL(m_glDepthStencilState.frontStencilFunc), m_glDepthStencilState.stencilRef, m_glDepthStencilState.stencilReadMask ); glStencilOpSeparate( GL_FRONT, ToOpenGL(m_glDepthStencilState.frontStencilFailOp), ToOpenGL(m_glDepthStencilState.frontStencilDepthFailOp), ToOpenGL(m_glDepthStencilState.frontStencilDepthPassOp) ); glStencilFuncSeparate( GL_BACK, ToOpenGL(m_glDepthStencilState.backStencilFunc), m_glDepthStencilState.stencilRef, m_glDepthStencilState.stencilReadMask ); glStencilOpSeparate( GL_BACK, ToOpenGL(m_glDepthStencilState.backStencilFailOp), ToOpenGL(m_glDepthStencilState.backStencilDepthFailOp), ToOpenGL(m_glDepthStencilState.backStencilDepthPassOp) ); } else { glDisable(GL_STENCIL_TEST); } } void OpenGLPipelineState::ApplyBlend() { if (m_glBlendState.blendEnable) { glEnable(GL_BLEND); glBlendFuncSeparate( ToOpenGL(m_glBlendState.srcBlend), ToOpenGL(m_glBlendState.dstBlend), ToOpenGL(m_glBlendState.srcBlendAlpha), ToOpenGL(m_glBlendState.dstBlendAlpha) ); glBlendEquationSeparate( ToOpenGL(m_glBlendState.blendOp), ToOpenGL(m_glBlendState.blendOpAlpha) ); glColorMask( (m_glBlendState.colorWriteMask & 1) != 0, (m_glBlendState.colorWriteMask & 2) != 0, (m_glBlendState.colorWriteMask & 4) != 0, (m_glBlendState.colorWriteMask & 8) != 0 ); } else { glDisable(GL_BLEND); } } void OpenGLPipelineState::ApplyRasterizer() { if (m_glRasterizerState.cullFaceEnable) { glEnable(GL_CULL_FACE); glCullFace(ToOpenGL(m_glRasterizerState.cullFace)); glFrontFace(ToOpenGL(m_glRasterizerState.frontFace)); } else { glDisable(GL_CULL_FACE); } glPolygonMode(GL_FRONT_AND_BACK, ToOpenGL(m_glRasterizerState.polygonMode)); if (m_glRasterizerState.multisampleEnable) { glEnable(GL_MULTISAMPLE); } else { glDisable(GL_MULTISAMPLE); } const bool polygonOffsetEnable = m_glRasterizerState.polygonOffsetFactor != 0.0f || m_glRasterizerState.polygonOffsetUnits != 0.0f; if (polygonOffsetEnable) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset( m_glRasterizerState.polygonOffsetFactor, m_glRasterizerState.polygonOffsetUnits); } else { glDisable(GL_POLYGON_OFFSET_FILL); } } void OpenGLPipelineState::ApplyViewport() { glViewport((GLint)m_viewportState.x, (GLint)m_viewportState.y, (GLsizei)m_viewportState.width, (GLsizei)m_viewportState.height); glDepthRange(m_viewportState.minDepth, m_viewportState.maxDepth); } void OpenGLPipelineState::ApplyScissor() { if (m_scissorState.enable) { glEnable(GL_SCISSOR_TEST); glScissor(m_scissorState.x, m_scissorState.y, m_scissorState.width, m_scissorState.height); } else { glDisable(GL_SCISSOR_TEST); } } 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) { m_clearColor[0] = r; m_clearColor[1] = g; m_clearColor[2] = b; m_clearColor[3] = a; glClearColor(r, g, b, a); } void OpenGLPipelineState::Clear(unsigned int buffers) { glClear(ToOpenGLClearBuffer(buffers)); } void OpenGLPipelineState::AttachShader(unsigned int program) { m_program = program; m_programAttached = true; glUseProgram(program); } void OpenGLPipelineState::DetachShader() { m_program = 0; m_programAttached = false; glUseProgram(0); } void OpenGLPipelineState::SetOwnedGraphicsShader(std::unique_ptr shader) { m_graphicsShader = std::move(shader); if (m_graphicsShader) { SetProgram(m_graphicsShader->GetID()); } else { DetachShader(); } } const OpenGLDepthStencilState& OpenGLPipelineState::GetOpenGLDepthStencilState() const { return m_glDepthStencilState; } const OpenGLBlendState& OpenGLPipelineState::GetOpenGLBlendState() const { return m_glBlendState; } const OpenGLRasterizerState& OpenGLPipelineState::GetOpenGLRasterizerState() const { return m_glRasterizerState; } } // namespace RHI } // namespace XCEngine