diff --git a/Source/Core/VideoBackends/Software/Tev.cpp b/Source/Core/VideoBackends/Software/Tev.cpp index be6f14d610..3c932b9566 100644 --- a/Source/Core/VideoBackends/Software/Tev.cpp +++ b/Source/Core/VideoBackends/Software/Tev.cpp @@ -838,8 +838,10 @@ void Tev::Draw() EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_OUTPUT); } - BoundingBox::Update(static_cast(Position[0]), static_cast(Position[0]), - static_cast(Position[1]), static_cast(Position[1])); + // The GC/Wii GPU rasterizes in 2x2 pixel groups, so bounding box values will be rounded to the + // extents of these groups, rather than the exact pixel. + BoundingBox::Update(static_cast(Position[0] & ~1), static_cast(Position[0] | 1), + static_cast(Position[1] & ~1), static_cast(Position[1] | 1)); #if ALLOW_TEV_DUMPS if (g_ActiveConfig.bDumpTevStages) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index a2bc73257e..16fb7766e9 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -492,19 +492,30 @@ void UpdateBoundingBox(float2 rawpos) {{ // such that width = right - left + 1. This has been verified on hardware. int2 pos = iround(rawpos * cefbscale + offset); + // The GC/Wii GPU rasterizes in 2x2 pixel groups, so bounding box values will be rounded to the + // extents of these groups, rather than the exact pixel. +#ifdef API_OPENGL + // Need to flip the operands for Y on OpenGL because of lower-left origin. + int2 pos_tl = int2(pos.x & ~1, pos.y | 1); + int2 pos_br = int2(pos.x | 1, pos.y & ~1); +#else + int2 pos_tl = pos & ~1; + int2 pos_br = pos | 1; +#endif + #ifdef SUPPORTS_SUBGROUP_REDUCTION if (CAN_USE_SUBGROUP_REDUCTION) {{ - int2 min_pos = IS_HELPER_INVOCATION ? int2(2147483647, 2147483647) : pos; - int2 max_pos = IS_HELPER_INVOCATION ? int2(-2147483648, -2147483648) : pos; + int2 min_pos = IS_HELPER_INVOCATION ? int2(2147483647, 2147483647) : pos_tl; + int2 max_pos = IS_HELPER_INVOCATION ? int2(-2147483648, -2147483648) : pos_br; SUBGROUP_MIN(min_pos); SUBGROUP_MAX(max_pos); if (IS_FIRST_ACTIVE_INVOCATION) UpdateBoundingBoxBuffer(min_pos, max_pos); }} else {{ - UpdateBoundingBoxBuffer(pos, pos); + UpdateBoundingBoxBuffer(pos_tl, pos_br); }} #else - UpdateBoundingBoxBuffer(pos, pos); + UpdateBoundingBoxBuffer(pos_tl, pos_br); #endif }} diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 0ff5b52902..f93d498fc6 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -187,18 +187,7 @@ void Renderer::ReinterpretPixelData(EFBReinterpretType convtype) u16 Renderer::BBoxRead(int index) { - u16 value = BBoxReadImpl(index); - - // The GC/Wii GPU rasterizes in 2x2 pixel groups, so bounding box values will be rounded to the - // extents of these groups, rather than the exact pixel. - // This would have been handled in the pixel shader, but all attempts to do so did not work on - // OpenGL/NVIDIA, due to presumably mystical driver behavior with atomics. - if (index == 0 || index == 2) - value &= ~1; - else - value |= 1; - - return value; + return BBoxReadImpl(index); } void Renderer::BBoxWrite(int index, u16 value)