mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	gl_rasterizer: Move alpha testing to the OpenGL pipeline
Removes the alpha testing code from each fragment shader invocation.
This commit is contained in:
		
							parent
							
								
									df509486c4
								
							
						
					
					
						commit
						b76df62c00
					
				@ -663,13 +663,10 @@ void RasterizerOpenGL::DrawArrays() {
 | 
				
			|||||||
    SyncCullMode();
 | 
					    SyncCullMode();
 | 
				
			||||||
    SyncPrimitiveRestart();
 | 
					    SyncPrimitiveRestart();
 | 
				
			||||||
    SyncScissorTest(state);
 | 
					    SyncScissorTest(state);
 | 
				
			||||||
    // Alpha Testing is synced on shaders.
 | 
					 | 
				
			||||||
    SyncTransformFeedback();
 | 
					    SyncTransformFeedback();
 | 
				
			||||||
    SyncPointState();
 | 
					    SyncPointState();
 | 
				
			||||||
    CheckAlphaTests();
 | 
					 | 
				
			||||||
    SyncPolygonOffset();
 | 
					    SyncPolygonOffset();
 | 
				
			||||||
    // TODO(bunnei): Sync framebuffer_scale uniform here
 | 
					    SyncAlphaTest();
 | 
				
			||||||
    // TODO(bunnei): Sync scissorbox uniform(s) here
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Draw the vertex batch
 | 
					    // Draw the vertex batch
 | 
				
			||||||
    const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
 | 
					    const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
 | 
				
			||||||
@ -1121,10 +1118,17 @@ void RasterizerOpenGL::SyncPolygonOffset() {
 | 
				
			|||||||
    state.polygon_offset.clamp = regs.polygon_offset_clamp;
 | 
					    state.polygon_offset.clamp = regs.polygon_offset_clamp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::CheckAlphaTests() {
 | 
					void RasterizerOpenGL::SyncAlphaTest() {
 | 
				
			||||||
    const auto& regs = system.GPU().Maxwell3D().regs;
 | 
					    const auto& regs = system.GPU().Maxwell3D().regs;
 | 
				
			||||||
    UNIMPLEMENTED_IF_MSG(regs.alpha_test_enabled != 0 && regs.rt_control.count > 1,
 | 
					    UNIMPLEMENTED_IF_MSG(regs.alpha_test_enabled != 0 && regs.rt_control.count > 1,
 | 
				
			||||||
                         "Alpha Testing is enabled with more than one rendertarget");
 | 
					                         "Alpha Testing is enabled with more than one rendertarget");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    state.alpha_test.enabled = regs.alpha_test_enabled;
 | 
				
			||||||
 | 
					    if (!state.alpha_test.enabled) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    state.alpha_test.func = MaxwellToGL::ComparisonOp(regs.alpha_test_func);
 | 
				
			||||||
 | 
					    state.alpha_test.ref = regs.alpha_test_ref;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenGL
 | 
					} // namespace OpenGL
 | 
				
			||||||
 | 
				
			|||||||
@ -166,8 +166,8 @@ private:
 | 
				
			|||||||
    /// Syncs the polygon offsets
 | 
					    /// Syncs the polygon offsets
 | 
				
			||||||
    void SyncPolygonOffset();
 | 
					    void SyncPolygonOffset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check asserts for alpha testing.
 | 
					    /// Syncs the alpha test state to match the guest state
 | 
				
			||||||
    void CheckAlphaTests();
 | 
					    void SyncAlphaTest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check for extension that are not strictly required
 | 
					    /// Check for extension that are not strictly required
 | 
				
			||||||
    /// but are needed for correct emulation
 | 
					    /// but are needed for correct emulation
 | 
				
			||||||
 | 
				
			|||||||
@ -1447,27 +1447,9 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
 | 
					        UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        code.AddLine("if (alpha_test[0] != 0) {{");
 | 
					 | 
				
			||||||
        ++code.scope;
 | 
					 | 
				
			||||||
        // We start on the register containing the alpha value in the first RT.
 | 
					 | 
				
			||||||
        u32 current_reg = 3;
 | 
					 | 
				
			||||||
        for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
 | 
					 | 
				
			||||||
            // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
 | 
					 | 
				
			||||||
            // multiple render targets are used.
 | 
					 | 
				
			||||||
            if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
 | 
					 | 
				
			||||||
                header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
 | 
					 | 
				
			||||||
                header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
 | 
					 | 
				
			||||||
                header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
 | 
					 | 
				
			||||||
                code.AddLine("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg));
 | 
					 | 
				
			||||||
                current_reg += 4;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        --code.scope;
 | 
					 | 
				
			||||||
        code.AddLine("}}");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Write the color outputs using the data in the shader registers, disabled
 | 
					        // Write the color outputs using the data in the shader registers, disabled
 | 
				
			||||||
        // rendertargets/components are skipped in the register assignment.
 | 
					        // rendertargets/components are skipped in the register assignment.
 | 
				
			||||||
        current_reg = 0;
 | 
					        u32 current_reg = 0;
 | 
				
			||||||
        for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
 | 
					        for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
 | 
				
			||||||
            // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
 | 
					            // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
 | 
				
			||||||
            for (u32 component = 0; component < 4; ++component) {
 | 
					            for (u32 component = 0; component < 4; ++component) {
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,6 @@ layout (location = 0) out vec4 position;
 | 
				
			|||||||
layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
 | 
					layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
 | 
				
			||||||
    vec4 viewport_flip;
 | 
					    vec4 viewport_flip;
 | 
				
			||||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
					    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
				
			||||||
    uvec4 alpha_test;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
)";
 | 
					)";
 | 
				
			||||||
@ -91,7 +90,6 @@ layout (location = 0) out vec4 position;
 | 
				
			|||||||
layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
 | 
					layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
 | 
				
			||||||
    vec4 viewport_flip;
 | 
					    vec4 viewport_flip;
 | 
				
			||||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
					    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
				
			||||||
    uvec4 alpha_test;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
)";
 | 
					)";
 | 
				
			||||||
@ -129,33 +127,8 @@ layout (location = 0) in noperspective vec4 position;
 | 
				
			|||||||
layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
 | 
					layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
 | 
				
			||||||
    vec4 viewport_flip;
 | 
					    vec4 viewport_flip;
 | 
				
			||||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
					    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
				
			||||||
    uvec4 alpha_test;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool AlphaFunc(in float value) {
 | 
					 | 
				
			||||||
    float ref = uintBitsToFloat(alpha_test[2]);
 | 
					 | 
				
			||||||
    switch (alpha_test[1]) {
 | 
					 | 
				
			||||||
        case 1:
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        case 2:
 | 
					 | 
				
			||||||
            return value < ref;
 | 
					 | 
				
			||||||
        case 3:
 | 
					 | 
				
			||||||
            return value == ref;
 | 
					 | 
				
			||||||
        case 4:
 | 
					 | 
				
			||||||
            return value <= ref;
 | 
					 | 
				
			||||||
        case 5:
 | 
					 | 
				
			||||||
            return value > ref;
 | 
					 | 
				
			||||||
        case 6:
 | 
					 | 
				
			||||||
            return value != ref;
 | 
					 | 
				
			||||||
        case 7:
 | 
					 | 
				
			||||||
            return value >= ref;
 | 
					 | 
				
			||||||
        case 8:
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
)";
 | 
					)";
 | 
				
			||||||
    const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
 | 
					    const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
 | 
				
			||||||
    ProgramResult program =
 | 
					    ProgramResult program =
 | 
				
			||||||
 | 
				
			|||||||
@ -48,17 +48,6 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shade
 | 
				
			|||||||
    viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
 | 
					    viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
 | 
				
			||||||
    viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
 | 
					    viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto func{static_cast<u32>(regs.alpha_test_func)};
 | 
					 | 
				
			||||||
    // Normalize the gl variants of opCompare to be the same as the normal variants
 | 
					 | 
				
			||||||
    const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never);
 | 
					 | 
				
			||||||
    if (func >= op_gl_variant_base) {
 | 
					 | 
				
			||||||
        func = func - op_gl_variant_base + 1U;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    alpha_test.enabled = regs.alpha_test_enabled;
 | 
					 | 
				
			||||||
    alpha_test.func = func;
 | 
					 | 
				
			||||||
    alpha_test.ref = regs.alpha_test_ref;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    instance_id = state.current_instance;
 | 
					    instance_id = state.current_instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Assign in which stage the position has to be flipped
 | 
					    // Assign in which stage the position has to be flipped
 | 
				
			||||||
 | 
				
			|||||||
@ -27,14 +27,8 @@ struct MaxwellUniformData {
 | 
				
			|||||||
        GLuint flip_stage;
 | 
					        GLuint flip_stage;
 | 
				
			||||||
        GLfloat y_direction;
 | 
					        GLfloat y_direction;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    struct alignas(16) {
 | 
					 | 
				
			||||||
        GLuint enabled;
 | 
					 | 
				
			||||||
        GLuint func;
 | 
					 | 
				
			||||||
        GLfloat ref;
 | 
					 | 
				
			||||||
        GLuint padding;
 | 
					 | 
				
			||||||
    } alpha_test;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect");
 | 
					static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect");
 | 
				
			||||||
static_assert(sizeof(MaxwellUniformData) < 16384,
 | 
					static_assert(sizeof(MaxwellUniformData) < 16384,
 | 
				
			||||||
              "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
 | 
					              "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -156,6 +156,10 @@ OpenGLState::OpenGLState() {
 | 
				
			|||||||
    polygon_offset.factor = 0.0f;
 | 
					    polygon_offset.factor = 0.0f;
 | 
				
			||||||
    polygon_offset.units = 0.0f;
 | 
					    polygon_offset.units = 0.0f;
 | 
				
			||||||
    polygon_offset.clamp = 0.0f;
 | 
					    polygon_offset.clamp = 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    alpha_test.enabled = false;
 | 
				
			||||||
 | 
					    alpha_test.func = GL_ALWAYS;
 | 
				
			||||||
 | 
					    alpha_test.ref = 0.0f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OpenGLState::ApplyDefaultState() {
 | 
					void OpenGLState::ApplyDefaultState() {
 | 
				
			||||||
@ -461,6 +465,14 @@ void OpenGLState::ApplyPolygonOffset() const {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OpenGLState::ApplyAlphaTest() const {
 | 
				
			||||||
 | 
					    Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled);
 | 
				
			||||||
 | 
					    if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref),
 | 
				
			||||||
 | 
					                  std::tie(alpha_test.func, alpha_test.ref))) {
 | 
				
			||||||
 | 
					        glAlphaFunc(alpha_test.func, alpha_test.ref);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OpenGLState::ApplyTextures() const {
 | 
					void OpenGLState::ApplyTextures() const {
 | 
				
			||||||
    bool has_delta{};
 | 
					    bool has_delta{};
 | 
				
			||||||
    std::size_t first{};
 | 
					    std::size_t first{};
 | 
				
			||||||
@ -533,6 +545,7 @@ void OpenGLState::Apply() const {
 | 
				
			|||||||
    ApplyTextures();
 | 
					    ApplyTextures();
 | 
				
			||||||
    ApplySamplers();
 | 
					    ApplySamplers();
 | 
				
			||||||
    ApplyPolygonOffset();
 | 
					    ApplyPolygonOffset();
 | 
				
			||||||
 | 
					    ApplyAlphaTest();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OpenGLState::EmulateViewportWithScissor() {
 | 
					void OpenGLState::EmulateViewportWithScissor() {
 | 
				
			||||||
 | 
				
			|||||||
@ -172,6 +172,12 @@ public:
 | 
				
			|||||||
        GLfloat clamp;
 | 
					        GLfloat clamp;
 | 
				
			||||||
    } polygon_offset;
 | 
					    } polygon_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					        bool enabled; // GL_ALPHA_TEST
 | 
				
			||||||
 | 
					        GLenum func;  // GL_ALPHA_TEST_FUNC
 | 
				
			||||||
 | 
					        GLfloat ref;  // GL_ALPHA_TEST_REF
 | 
				
			||||||
 | 
					    } alpha_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE
 | 
					    std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OpenGLState();
 | 
					    OpenGLState();
 | 
				
			||||||
@ -215,6 +221,7 @@ public:
 | 
				
			|||||||
    void ApplySamplers() const;
 | 
					    void ApplySamplers() const;
 | 
				
			||||||
    void ApplyDepthClamp() const;
 | 
					    void ApplyDepthClamp() const;
 | 
				
			||||||
    void ApplyPolygonOffset() const;
 | 
					    void ApplyPolygonOffset() const;
 | 
				
			||||||
 | 
					    void ApplyAlphaTest() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Set the initial OpenGL state
 | 
					    /// Set the initial OpenGL state
 | 
				
			||||||
    static void ApplyDefaultState();
 | 
					    static void ApplyDefaultState();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user