PICA: Scissor fixes and cleanups

This commit is contained in:
Yuri Kunde Schlesner 2016-01-24 22:59:16 -08:00
parent f9be06b15f
commit f0b9bc14b6
5 changed files with 39 additions and 45 deletions

View File

@ -128,22 +128,14 @@ struct Regs {
BitField<0, 2, ScissorMode> mode; BitField<0, 2, ScissorMode> mode;
union { union {
BitField< 0, 16, u32> right; BitField< 0, 16, u32> x1;
BitField<16, 16, u32> bottom; BitField<16, 16, u32> y1;
}; };
union { union {
BitField< 0, 16, u32> left_minus_1; BitField< 0, 16, u32> x2;
BitField<16, 16, u32> top_minus_1; BitField<16, 16, u32> y2;
}; };
u32 GetTop() const {
return top_minus_1 + 1;
}
u32 GetLeft() const {
return left_minus_1 + 1;
}
} scissor_test; } scissor_test;
union { union {

View File

@ -344,17 +344,18 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
// Convert the scissor box coordinates to 12.4 fixed point // Convert the scissor box coordinates to 12.4 fixed point
u16 scissor_left = (u16)(regs.scissor_test.GetLeft() << 4); u16 scissor_x1 = (u16)( regs.scissor_test.x1 << 4);
u16 scissor_top = (u16)(regs.scissor_test.GetTop() << 4); u16 scissor_y1 = (u16)( regs.scissor_test.y1 << 4);
u16 scissor_right = (u16)(regs.scissor_test.right << 4); // x2,y2 have +1 added to cover the entire sub-pixel area
u16 scissor_bottom = (u16)(regs.scissor_test.bottom << 4); u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4);
u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4);
if (regs.scissor_test.mode == Regs::ScissorMode::Include) { if (regs.scissor_test.mode == Regs::ScissorMode::Include) {
// Calculate the new bounds // Calculate the new bounds
min_x = std::max(min_x, scissor_right); min_x = std::max(min_x, scissor_x1);
min_y = std::max(min_y, scissor_bottom); min_y = std::max(min_y, scissor_y1);
max_x = std::min(max_x, scissor_left); max_x = std::min(max_x, scissor_x2);
max_y = std::min(max_y, scissor_top); max_y = std::min(max_y, scissor_y2);
} }
min_x &= Fix12P4::IntMask(); min_x &= Fix12P4::IntMask();
@ -397,9 +398,9 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
for (u16 x = min_x + 8; x < max_x; x += 0x10) { for (u16 x = min_x + 8; x < max_x; x += 0x10) {
// Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude // Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude
if (regs.scissor_test.mode == Regs::ScissorMode::Exclude && if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) {
x >= scissor_right && x <= scissor_left && if (x >= scissor_x1 && x < scissor_x2 &&
y >= scissor_bottom && y <= scissor_top) { y >= scissor_y1 && y < scissor_y2)
continue; continue;
} }

View File

@ -357,8 +357,8 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
case PICA_REG_INDEX(scissor_test.mode): case PICA_REG_INDEX(scissor_test.mode):
shader_dirty = true; shader_dirty = true;
break; break;
case PICA_REG_INDEX(scissor_test.right): case PICA_REG_INDEX(scissor_test.x1): // and y1
case PICA_REG_INDEX(scissor_test.left_minus_1): case PICA_REG_INDEX(scissor_test.x2): // and y2
SyncScissorTest(); SyncScissorTest();
break; break;
@ -1179,15 +1179,15 @@ void RasterizerOpenGL::SyncDepthTest() {
void RasterizerOpenGL::SyncScissorTest() { void RasterizerOpenGL::SyncScissorTest() {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
if (uniform_block_data.data.scissor_right != regs.scissor_test.right || if (uniform_block_data.data.scissor_x1 != regs.scissor_test.x1 ||
uniform_block_data.data.scissor_bottom != regs.scissor_test.bottom || uniform_block_data.data.scissor_y1 != regs.scissor_test.y1 ||
uniform_block_data.data.scissor_left != regs.scissor_test.GetLeft() || uniform_block_data.data.scissor_x2 != regs.scissor_test.x2 ||
uniform_block_data.data.scissor_top != regs.scissor_test.GetTop()) { uniform_block_data.data.scissor_y2 != regs.scissor_test.y2) {
uniform_block_data.data.scissor_right = regs.scissor_test.right; uniform_block_data.data.scissor_x1 = regs.scissor_test.x1;
uniform_block_data.data.scissor_bottom = regs.scissor_test.bottom; uniform_block_data.data.scissor_y1 = regs.scissor_test.y1;
uniform_block_data.data.scissor_left = regs.scissor_test.GetLeft(); uniform_block_data.data.scissor_x2 = regs.scissor_test.x2;
uniform_block_data.data.scissor_top = regs.scissor_test.GetTop(); uniform_block_data.data.scissor_y2 = regs.scissor_test.y2;
uniform_block_data.dirty = true; uniform_block_data.dirty = true;
} }
} }

View File

@ -331,10 +331,10 @@ private:
GLint alphatest_ref; GLint alphatest_ref;
GLfloat depth_scale; GLfloat depth_scale;
GLfloat depth_offset; GLfloat depth_offset;
GLint scissor_right; GLint scissor_x1;
GLint scissor_bottom; GLint scissor_y1;
GLint scissor_left; GLint scissor_x2;
GLint scissor_top; GLint scissor_y2;
alignas(16) GLvec3 fog_color; alignas(16) GLvec3 fog_color;
alignas(16) GLvec3 lighting_global_ambient; alignas(16) GLvec3 lighting_global_ambient;
LightSrc light_src[8]; LightSrc light_src[8];

View File

@ -557,10 +557,10 @@ layout (std140) uniform shader_data {
int alphatest_ref; int alphatest_ref;
float depth_scale; float depth_scale;
float depth_offset; float depth_offset;
int scissor_right; int scissor_x1;
int scissor_bottom; int scissor_y1;
int scissor_left; int scissor_x2;
int scissor_top; int scissor_y2;
vec3 fog_color; vec3 fog_color;
vec3 lighting_global_ambient; vec3 lighting_global_ambient;
LightSrc light_src[NUM_LIGHTS]; LightSrc light_src[NUM_LIGHTS];
@ -589,13 +589,14 @@ vec4 secondary_fragment_color = vec4(0.0);
} }
// Append the scissor test // Append the scissor test
if (state.scissor_test_mode == Regs::ScissorMode::Include || state.scissor_test_mode == Regs::ScissorMode::Exclude) { if (state.scissor_test_mode != Regs::ScissorMode::Disabled) {
out += "if (scissor_left <= scissor_right || scissor_top <= scissor_bottom) discard;\n";
out += "if ("; out += "if (";
// Negate the condition if we have to keep only the pixels outside the scissor box // Negate the condition if we have to keep only the pixels outside the scissor box
if (state.scissor_test_mode == Regs::ScissorMode::Include) if (state.scissor_test_mode == Regs::ScissorMode::Include)
out += "!"; out += "!";
out += "(gl_FragCoord.x >= scissor_right && gl_FragCoord.x <= scissor_left && gl_FragCoord.y >= scissor_bottom && gl_FragCoord.y <= scissor_top)) discard;\n"; // x2,y2 have +1 added to cover the entire pixel area
out += "(gl_FragCoord.x >= scissor_x1 && gl_FragCoord.x < scissor_x2 + 1 && "
"gl_FragCoord.y >= scissor_y1 && gl_FragCoord.y < scissor_y2 + 1)) discard;\n";
} }
out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n";