Merge pull request #1798 from ReinUsesLisp/y-direction
gl_shader_decompiler: Implement S2R's Y_DIRECTION
This commit is contained in:
		@@ -728,6 +728,7 @@ public:
 | 
			
		||||
                u32 frag_color_clamp;
 | 
			
		||||
 | 
			
		||||
                union {
 | 
			
		||||
                    BitField<0, 1, u32> y_negate;
 | 
			
		||||
                    BitField<4, 1, u32> triangle_rast_flip;
 | 
			
		||||
                } screen_y_control;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -867,7 +867,8 @@ private:
 | 
			
		||||
            // vertex shader, and what's the value of the fourth element when inside a Tess Eval
 | 
			
		||||
            // shader.
 | 
			
		||||
            ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
 | 
			
		||||
            return "vec4(0, 0, uintBitsToFloat(instance_id.x), uintBitsToFloat(gl_VertexID))";
 | 
			
		||||
            // Config pack's first value is instance_id.
 | 
			
		||||
            return "vec4(0, 0, uintBitsToFloat(config_pack[0]), uintBitsToFloat(gl_VertexID))";
 | 
			
		||||
        case Attribute::Index::FrontFacing:
 | 
			
		||||
            // TODO(Subv): Find out what the values are for the other elements.
 | 
			
		||||
            ASSERT(stage == Maxwell3D::Regs::ShaderStage::Fragment);
 | 
			
		||||
@@ -3653,6 +3654,11 @@ private:
 | 
			
		||||
                    regs.SetRegisterToInteger(instr.gpr0, false, 0, "0u", 1, 1);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case Tegra::Shader::SystemVariable::Ydirection: {
 | 
			
		||||
                    // Config pack's third value is Y_NEGATE's state.
 | 
			
		||||
                    regs.SetRegisterToFloat(instr.gpr0, 0, "uintBitsToFloat(config_pack[2])", 1, 1);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                default: {
 | 
			
		||||
                    UNIMPLEMENTED_MSG("Unhandled system move: {}",
 | 
			
		||||
                                      static_cast<u32>(instr.sys20.Value()));
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,7 @@ layout (location = 0) out vec4 position;
 | 
			
		||||
 | 
			
		||||
layout(std140) uniform vs_config {
 | 
			
		||||
    vec4 viewport_flip;
 | 
			
		||||
    uvec4 instance_id;
 | 
			
		||||
    uvec4 flip_stage;
 | 
			
		||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
			
		||||
    uvec4 alpha_test;
 | 
			
		||||
};
 | 
			
		||||
)";
 | 
			
		||||
@@ -63,7 +62,8 @@ void main() {
 | 
			
		||||
    out += R"(
 | 
			
		||||
 | 
			
		||||
    // Check if the flip stage is VertexB
 | 
			
		||||
    if (flip_stage[0] == 1) {
 | 
			
		||||
    // Config pack's second value is flip_stage
 | 
			
		||||
    if (config_pack[1] == 1) {
 | 
			
		||||
        // Viewport can be flipped, which is unsupported by glViewport
 | 
			
		||||
        position.xy *= viewport_flip.xy;
 | 
			
		||||
    }
 | 
			
		||||
@@ -71,7 +71,7 @@ void main() {
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): This is likely a hack, position.w should be interpolated as 1.0
 | 
			
		||||
    // For now, this is here to bring order in lieu of proper emulation
 | 
			
		||||
    if (flip_stage[0] == 1) {
 | 
			
		||||
    if (config_pack[1] == 1) {
 | 
			
		||||
        position.w = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -101,8 +101,7 @@ layout (location = 0) out vec4 position;
 | 
			
		||||
 | 
			
		||||
layout (std140) uniform gs_config {
 | 
			
		||||
    vec4 viewport_flip;
 | 
			
		||||
    uvec4 instance_id;
 | 
			
		||||
    uvec4 flip_stage;
 | 
			
		||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
			
		||||
    uvec4 alpha_test;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -139,8 +138,7 @@ layout (location = 0) in vec4 position;
 | 
			
		||||
 | 
			
		||||
layout (std140) uniform fs_config {
 | 
			
		||||
    vec4 viewport_flip;
 | 
			
		||||
    uvec4 instance_id;
 | 
			
		||||
    uvec4 flip_stage;
 | 
			
		||||
    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
 | 
			
		||||
    uvec4 alpha_test;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,16 +27,18 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh
 | 
			
		||||
    alpha_test.func = func;
 | 
			
		||||
    alpha_test.ref = regs.alpha_test_ref;
 | 
			
		||||
 | 
			
		||||
    // We only assign the instance to the first component of the vector, the rest is just padding.
 | 
			
		||||
    instance_id[0] = state.current_instance;
 | 
			
		||||
    instance_id = state.current_instance;
 | 
			
		||||
 | 
			
		||||
    // Assign in which stage the position has to be flipped
 | 
			
		||||
    // (the last stage before the fragment shader).
 | 
			
		||||
    if (gpu.regs.shader_config[static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry)].enable) {
 | 
			
		||||
        flip_stage[0] = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
 | 
			
		||||
        flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
 | 
			
		||||
    } else {
 | 
			
		||||
        flip_stage[0] = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
 | 
			
		||||
        flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
 | 
			
		||||
    y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace OpenGL::GLShader
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,11 @@ using Tegra::Engines::Maxwell3D;
 | 
			
		||||
struct MaxwellUniformData {
 | 
			
		||||
    void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
 | 
			
		||||
    alignas(16) GLvec4 viewport_flip;
 | 
			
		||||
    alignas(16) GLuvec4 instance_id;
 | 
			
		||||
    alignas(16) GLuvec4 flip_stage;
 | 
			
		||||
    struct alignas(16) {
 | 
			
		||||
        GLuint instance_id;
 | 
			
		||||
        GLuint flip_stage;
 | 
			
		||||
        GLfloat y_direction;
 | 
			
		||||
    };
 | 
			
		||||
    struct alignas(16) {
 | 
			
		||||
        GLuint enabled;
 | 
			
		||||
        GLuint func;
 | 
			
		||||
@@ -30,7 +33,7 @@ struct MaxwellUniformData {
 | 
			
		||||
        GLuint padding;
 | 
			
		||||
    } alpha_test;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(MaxwellUniformData) == 64, "MaxwellUniformData structure size is incorrect");
 | 
			
		||||
static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect");
 | 
			
		||||
static_assert(sizeof(MaxwellUniformData) < 16384,
 | 
			
		||||
              "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user