1
0
Fork 0
forked from suyu/suyu

GPU: Calculate the correct viewport dimensions based on the scale and translate registers.

This is how nouveau calculates the viewport width and height. For some reason some games set 0xFFFF in the VIEWPORT_HORIZ and VIEWPORT_VERT registers, maybe those are a misnomer and actually refer to something else?
This commit is contained in:
Subv 2018-06-04 16:36:54 -05:00
parent 049ce242a4
commit 5d55403f94
2 changed files with 30 additions and 14 deletions

View file

@ -354,10 +354,35 @@ public:
f32 scale_x; f32 scale_x;
f32 scale_y; f32 scale_y;
f32 scale_z; f32 scale_z;
u32 translate_x; f32 translate_x;
u32 translate_y; f32 translate_y;
u32 translate_z; f32 translate_z;
INSERT_PADDING_WORDS(2); INSERT_PADDING_WORDS(2);
MathUtil::Rectangle<s32> GetRect() const {
return {
GetX(), // left
GetY() + GetHeight(), // top
GetX() + GetWidth(), // right
GetY() // bottom
};
};
s32 GetX() const {
return static_cast<s32>(std::max(0.0f, translate_x - std::fabs(scale_x)));
}
s32 GetY() const {
return static_cast<s32>(std::max(0.0f, translate_y - std::fabs(scale_y)));
}
s32 GetWidth() const {
return static_cast<s32>(translate_x + std::fabs(scale_x)) - GetX();
}
s32 GetHeight() const {
return static_cast<s32>(translate_y + std::fabs(scale_y)) - GetY();
}
} viewport_transform[NumViewports]; } viewport_transform[NumViewports];
struct { struct {
@ -371,15 +396,6 @@ public:
}; };
float depth_range_near; float depth_range_near;
float depth_range_far; float depth_range_far;
MathUtil::Rectangle<s32> GetRect() const {
return {
static_cast<s32>(x), // left
static_cast<s32>(y + height), // top
static_cast<s32>(x + width), // right
static_cast<s32>(y) // bottom
};
};
} viewport[NumViewports]; } viewport[NumViewports];
INSERT_PADDING_WORDS(0x1D); INSERT_PADDING_WORDS(0x1D);

View file

@ -298,7 +298,7 @@ void RasterizerOpenGL::DrawArrays() {
const bool has_stencil = false; const bool has_stencil = false;
const bool using_color_fb = true; const bool using_color_fb = true;
const bool using_depth_fb = false; const bool using_depth_fb = false;
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport[0].GetRect()}; const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
const bool write_color_fb = const bool write_color_fb =
state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE || state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
@ -702,7 +702,7 @@ void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
void RasterizerOpenGL::SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale) { void RasterizerOpenGL::SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale) {
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport[0].GetRect()}; const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
state.viewport.x = static_cast<GLint>(surfaces_rect.left) + viewport_rect.left * res_scale; state.viewport.x = static_cast<GLint>(surfaces_rect.left) + viewport_rect.left * res_scale;
state.viewport.y = static_cast<GLint>(surfaces_rect.bottom) + viewport_rect.bottom * res_scale; state.viewport.y = static_cast<GLint>(surfaces_rect.bottom) + viewport_rect.bottom * res_scale;