GPU: Implemented the logic op functionality of the GPU.

This will ASSERT if blending is enabled at the same time as logic ops.
This commit is contained in:
Subv 2018-08-20 18:44:47 -05:00
parent f24ab6d9e6
commit 2b9eee4d1e
3 changed files with 61 additions and 0 deletions

View file

@ -449,6 +449,7 @@ void RasterizerOpenGL::DrawArrays() {
SyncDepthTestState(); SyncDepthTestState();
SyncBlendState(); SyncBlendState();
SyncLogicOpState();
SyncCullMode(); SyncCullMode();
// TODO(bunnei): Sync framebuffer_scale uniform here // TODO(bunnei): Sync framebuffer_scale uniform here
@ -847,6 +848,9 @@ void RasterizerOpenGL::SyncBlendState() {
if (!state.blend.enabled) if (!state.blend.enabled)
return; return;
ASSERT_MSG(regs.logic_op.enable == 0,
"Blending and logic op can't be enabled at the same time.");
ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented");
ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented");
state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb);
@ -856,3 +860,17 @@ void RasterizerOpenGL::SyncBlendState() {
state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a);
state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a);
} }
void RasterizerOpenGL::SyncLogicOpState() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
// TODO(Subv): Support more than just render target 0.
state.logic_op.enabled = regs.logic_op.enable != 0;
if (!state.logic_op.enabled)
return;
ASSERT_MSG(regs.blend.enable == 0, "Blending and logic op can't be enabled at the same time.");
state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
}

View file

@ -141,6 +141,9 @@ private:
/// Syncs the blend state to match the guest state /// Syncs the blend state to match the guest state
void SyncBlendState(); void SyncBlendState();
/// Syncs the LogicOp state to match the guest state
void SyncLogicOpState();
bool has_ARB_direct_state_access = false; bool has_ARB_direct_state_access = false;
bool has_ARB_separate_shader_objects = false; bool has_ARB_separate_shader_objects = false;
bool has_ARB_vertex_attrib_binding = false; bool has_ARB_vertex_attrib_binding = false;

View file

@ -317,4 +317,44 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
return {}; return {};
} }
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
switch (operation) {
case Maxwell::LogicOperation::Clear:
return GL_CLEAR;
case Maxwell::LogicOperation::And:
return GL_AND;
case Maxwell::LogicOperation::AndReverse:
return GL_AND_REVERSE;
case Maxwell::LogicOperation::Copy:
return GL_COPY;
case Maxwell::LogicOperation::AndInverted:
return GL_AND_INVERTED;
case Maxwell::LogicOperation::NoOp:
return GL_NOOP;
case Maxwell::LogicOperation::Xor:
return GL_XOR;
case Maxwell::LogicOperation::Or:
return GL_OR;
case Maxwell::LogicOperation::Nor:
return GL_NOR;
case Maxwell::LogicOperation::Equiv:
return GL_EQUIV;
case Maxwell::LogicOperation::Invert:
return GL_INVERT;
case Maxwell::LogicOperation::OrReverse:
return GL_OR_REVERSE;
case Maxwell::LogicOperation::CopyInverted:
return GL_COPY_INVERTED;
case Maxwell::LogicOperation::OrInverted:
return GL_OR_INVERTED;
case Maxwell::LogicOperation::Nand:
return GL_NAND;
case Maxwell::LogicOperation::Set:
return GL_SET;
}
LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
UNREACHABLE();
return {};
}
} // namespace MaxwellToGL } // namespace MaxwellToGL