gl_rasterizer: Implement stencil test.
- Used by Splatoon 2.
This commit is contained in:
parent
da3da6be90
commit
a4ac3bed6c
3 changed files with 58 additions and 4 deletions
|
@ -316,16 +316,14 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
|
||||||
using_color_fb = false;
|
using_color_fb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bunnei): Implement this
|
const bool has_stencil = regs.stencil_enable;
|
||||||
const bool has_stencil = false;
|
|
||||||
|
|
||||||
const bool write_color_fb =
|
const bool write_color_fb =
|
||||||
state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
|
state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
|
||||||
state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
|
state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
|
||||||
|
|
||||||
const bool write_depth_fb =
|
const bool write_depth_fb =
|
||||||
(state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
|
(state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
|
||||||
(has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0);
|
(has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
|
||||||
|
|
||||||
Surface color_surface;
|
Surface color_surface;
|
||||||
Surface depth_surface;
|
Surface depth_surface;
|
||||||
|
@ -481,6 +479,7 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true);
|
ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true);
|
||||||
|
|
||||||
SyncDepthTestState();
|
SyncDepthTestState();
|
||||||
|
SyncStencilTestState();
|
||||||
SyncBlendState();
|
SyncBlendState();
|
||||||
SyncLogicOpState();
|
SyncLogicOpState();
|
||||||
SyncCullMode();
|
SyncCullMode();
|
||||||
|
@ -871,6 +870,34 @@ void RasterizerOpenGL::SyncDepthTestState() {
|
||||||
state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
|
state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
state.stencil.test_enabled = regs.stencil_enable != 0;
|
||||||
|
|
||||||
|
if (!regs.stencil_enable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bunnei): Verify behavior when this is not set
|
||||||
|
ASSERT(regs.stencil_two_side_enable);
|
||||||
|
|
||||||
|
state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);
|
||||||
|
state.stencil.front.test_ref = regs.stencil_front_func_ref;
|
||||||
|
state.stencil.front.test_mask = regs.stencil_front_func_mask;
|
||||||
|
state.stencil.front.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_fail);
|
||||||
|
state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail);
|
||||||
|
state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass);
|
||||||
|
state.stencil.front.write_mask = regs.stencil_front_mask;
|
||||||
|
|
||||||
|
state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func);
|
||||||
|
state.stencil.back.test_ref = regs.stencil_back_func_ref;
|
||||||
|
state.stencil.back.test_mask = regs.stencil_back_func_mask;
|
||||||
|
state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail);
|
||||||
|
state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail);
|
||||||
|
state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass);
|
||||||
|
state.stencil.back.write_mask = regs.stencil_back_mask;
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendState() {
|
void RasterizerOpenGL::SyncBlendState() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,9 @@ private:
|
||||||
/// Syncs the depth test state to match the guest state
|
/// Syncs the depth test state to match the guest state
|
||||||
void SyncDepthTestState();
|
void SyncDepthTestState();
|
||||||
|
|
||||||
|
/// Syncs the stencil test state to match the guest state
|
||||||
|
void SyncStencilTestState();
|
||||||
|
|
||||||
/// Syncs the blend state to match the guest state
|
/// Syncs the blend state to match the guest state
|
||||||
void SyncBlendState();
|
void SyncBlendState();
|
||||||
|
|
||||||
|
|
|
@ -295,6 +295,30 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
|
||||||
|
switch (stencil) {
|
||||||
|
case Maxwell::StencilOp::Keep:
|
||||||
|
return GL_KEEP;
|
||||||
|
case Maxwell::StencilOp::Zero:
|
||||||
|
return GL_ZERO;
|
||||||
|
case Maxwell::StencilOp::Replace:
|
||||||
|
return GL_REPLACE;
|
||||||
|
case Maxwell::StencilOp::Incr:
|
||||||
|
return GL_INCR;
|
||||||
|
case Maxwell::StencilOp::Decr:
|
||||||
|
return GL_DECR;
|
||||||
|
case Maxwell::StencilOp::Invert:
|
||||||
|
return GL_INVERT;
|
||||||
|
case Maxwell::StencilOp::IncrWrap:
|
||||||
|
return GL_INCR_WRAP;
|
||||||
|
case Maxwell::StencilOp::DecrWrap:
|
||||||
|
return GL_DECR_WRAP;
|
||||||
|
}
|
||||||
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
|
inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
|
||||||
switch (front_face) {
|
switch (front_face) {
|
||||||
case Maxwell::Cull::FrontFace::ClockWise:
|
case Maxwell::Cull::FrontFace::ClockWise:
|
||||||
|
|
Loading…
Reference in a new issue