diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index b379d80570..d4fcedace5 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -319,7 +319,15 @@ public: } } rt[NumRenderTargets]; - INSERT_PADDING_WORDS(0x80); + struct { + f32 scale_x; + f32 scale_y; + f32 scale_z; + u32 translate_x; + u32 translate_y; + u32 translate_z; + INSERT_PADDING_WORDS(2); + } viewport_transform[NumViewports]; struct { union { @@ -649,6 +657,7 @@ private: "Field " #field_name " has invalid position") ASSERT_REG_POSITION(rt, 0x200); +ASSERT_REG_POSITION(viewport_transform[0], 0x280); ASSERT_REG_POSITION(viewport, 0x300); ASSERT_REG_POSITION(vertex_buffer, 0x35D); ASSERT_REG_POSITION(zeta, 0x3F8); diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 8b7f17601f..254f6e2c37 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -29,9 +29,15 @@ out gl_PerVertex { out vec4 position; +layout (std140) uniform vs_config { + vec4 viewport_flip; +}; + void main() { exec_shader(); + // Viewport can be flipped, which is unsupported by glViewport + position.xy *= viewport_flip.xy; gl_Position = position; } )"; @@ -52,6 +58,10 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSCo in vec4 position; out vec4 color; +layout (std140) uniform fs_config { + vec4 viewport_flip; +}; + uniform sampler2D tex[32]; void main() { diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 85b838faa6..17b3925a0d 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -53,6 +53,12 @@ void SetShaderSamplerBindings(GLuint shader) { } // namespace Impl -void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {} +void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { + const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; + + // TODO(bunnei): Support more than one viewport + viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0 : 1.0; + viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0 : 1.0; +} } // namespace GLShader diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index be63320e0d..e963b4b7e0 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -30,10 +30,9 @@ void SetShaderSamplerBindings(GLuint shader); // Not following that rule will cause problems on some AMD drivers. struct MaxwellUniformData { void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); - // TODO(Subv): Use this for something. + alignas(16) GLvec4 viewport_flip; }; -// static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is -// incorrect"); +static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect"); static_assert(sizeof(MaxwellUniformData) < 16384, "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");