Merge pull request #1124 from Subv/logic_ops
GPU: Implemented logic ops.
This commit is contained in:
		
						commit
						125d7122ac
					
				@ -311,6 +311,25 @@ public:
 | 
				
			|||||||
            AlwaysOld = 8,
 | 
					            AlwaysOld = 8,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        enum class LogicOperation : u32 {
 | 
				
			||||||
 | 
					            Clear = 0x1500,
 | 
				
			||||||
 | 
					            And = 0x1501,
 | 
				
			||||||
 | 
					            AndReverse = 0x1502,
 | 
				
			||||||
 | 
					            Copy = 0x1503,
 | 
				
			||||||
 | 
					            AndInverted = 0x1504,
 | 
				
			||||||
 | 
					            NoOp = 0x1505,
 | 
				
			||||||
 | 
					            Xor = 0x1506,
 | 
				
			||||||
 | 
					            Or = 0x1507,
 | 
				
			||||||
 | 
					            Nor = 0x1508,
 | 
				
			||||||
 | 
					            Equiv = 0x1509,
 | 
				
			||||||
 | 
					            Invert = 0x150A,
 | 
				
			||||||
 | 
					            OrReverse = 0x150B,
 | 
				
			||||||
 | 
					            CopyInverted = 0x150C,
 | 
				
			||||||
 | 
					            OrInverted = 0x150D,
 | 
				
			||||||
 | 
					            Nand = 0x150E,
 | 
				
			||||||
 | 
					            Set = 0x150F,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct Cull {
 | 
					        struct Cull {
 | 
				
			||||||
            enum class FrontFace : u32 {
 | 
					            enum class FrontFace : u32 {
 | 
				
			||||||
                ClockWise = 0x0900,
 | 
					                ClockWise = 0x0900,
 | 
				
			||||||
@ -695,7 +714,14 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                Cull cull;
 | 
					                Cull cull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                INSERT_PADDING_WORDS(0x2B);
 | 
					                INSERT_PADDING_WORDS(0x28);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                struct {
 | 
				
			||||||
 | 
					                    u32 enable;
 | 
				
			||||||
 | 
					                    LogicOperation operation;
 | 
				
			||||||
 | 
					                } logic_op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                INSERT_PADDING_WORDS(0x1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                union {
 | 
					                union {
 | 
				
			||||||
                    u32 raw;
 | 
					                    u32 raw;
 | 
				
			||||||
@ -942,6 +968,7 @@ ASSERT_REG_POSITION(draw, 0x585);
 | 
				
			|||||||
ASSERT_REG_POSITION(index_array, 0x5F2);
 | 
					ASSERT_REG_POSITION(index_array, 0x5F2);
 | 
				
			||||||
ASSERT_REG_POSITION(instanced_arrays, 0x620);
 | 
					ASSERT_REG_POSITION(instanced_arrays, 0x620);
 | 
				
			||||||
ASSERT_REG_POSITION(cull, 0x646);
 | 
					ASSERT_REG_POSITION(cull, 0x646);
 | 
				
			||||||
 | 
					ASSERT_REG_POSITION(logic_op, 0x671);
 | 
				
			||||||
ASSERT_REG_POSITION(clear_buffers, 0x674);
 | 
					ASSERT_REG_POSITION(clear_buffers, 0x674);
 | 
				
			||||||
ASSERT_REG_POSITION(query, 0x6C0);
 | 
					ASSERT_REG_POSITION(query, 0x6C0);
 | 
				
			||||||
ASSERT_REG_POSITION(vertex_array[0], 0x700);
 | 
					ASSERT_REG_POSITION(vertex_array[0], 0x700);
 | 
				
			||||||
 | 
				
			|||||||
@ -450,6 +450,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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -142,6 +142,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;
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,8 @@ OpenGLState::OpenGLState() {
 | 
				
			|||||||
    blend.color.blue = 0.0f;
 | 
					    blend.color.blue = 0.0f;
 | 
				
			||||||
    blend.color.alpha = 0.0f;
 | 
					    blend.color.alpha = 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    logic_op = GL_COPY;
 | 
					    logic_op.enabled = false;
 | 
				
			||||||
 | 
					    logic_op.operation = GL_COPY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto& texture_unit : texture_units) {
 | 
					    for (auto& texture_unit : texture_units) {
 | 
				
			||||||
        texture_unit.Reset();
 | 
					        texture_unit.Reset();
 | 
				
			||||||
@ -148,11 +149,10 @@ void OpenGLState::Apply() const {
 | 
				
			|||||||
    // Blending
 | 
					    // Blending
 | 
				
			||||||
    if (blend.enabled != cur_state.blend.enabled) {
 | 
					    if (blend.enabled != cur_state.blend.enabled) {
 | 
				
			||||||
        if (blend.enabled) {
 | 
					        if (blend.enabled) {
 | 
				
			||||||
 | 
					            ASSERT(!logic_op.enabled);
 | 
				
			||||||
            glEnable(GL_BLEND);
 | 
					            glEnable(GL_BLEND);
 | 
				
			||||||
            glDisable(GL_COLOR_LOGIC_OP);
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            glDisable(GL_BLEND);
 | 
					            glDisable(GL_BLEND);
 | 
				
			||||||
            glEnable(GL_COLOR_LOGIC_OP);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -176,8 +176,18 @@ void OpenGLState::Apply() const {
 | 
				
			|||||||
        glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
 | 
					        glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (logic_op != cur_state.logic_op) {
 | 
					    // Logic Operation
 | 
				
			||||||
        glLogicOp(logic_op);
 | 
					    if (logic_op.enabled != cur_state.logic_op.enabled) {
 | 
				
			||||||
 | 
					        if (logic_op.enabled) {
 | 
				
			||||||
 | 
					            ASSERT(!blend.enabled);
 | 
				
			||||||
 | 
					            glEnable(GL_COLOR_LOGIC_OP);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glDisable(GL_COLOR_LOGIC_OP);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (logic_op.operation != cur_state.logic_op.operation) {
 | 
				
			||||||
 | 
					        glLogicOp(logic_op.operation);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Textures
 | 
					    // Textures
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,10 @@ public:
 | 
				
			|||||||
        } color; // GL_BLEND_COLOR
 | 
					        } color; // GL_BLEND_COLOR
 | 
				
			||||||
    } blend;
 | 
					    } blend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLenum logic_op; // GL_LOGIC_OP_MODE
 | 
					    struct {
 | 
				
			||||||
 | 
					        bool enabled; // GL_LOGIC_OP_MODE
 | 
				
			||||||
 | 
					        GLenum operation;
 | 
				
			||||||
 | 
					    } logic_op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 3 texture units - one for each that is used in PICA fragment shader emulation
 | 
					    // 3 texture units - one for each that is used in PICA fragment shader emulation
 | 
				
			||||||
    struct TextureUnit {
 | 
					    struct TextureUnit {
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user