Merge pull request #9765 from Techjar/bbox-pixel-quads-2-electric-boogaloo

VideoCommon: Move bounding box pixel quads rounding to shader
This commit is contained in:
Connor McLaughlin 2021-05-29 17:00:14 +10:00 committed by GitHub
commit b31d4400e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 52 additions and 69 deletions

View File

@ -264,17 +264,17 @@ void Renderer::UnbindTexture(const AbstractTexture* texture)
D3D::stateman->ApplyTextures(); D3D::stateman->ApplyTextures();
} }
u16 Renderer::BBoxReadImpl(int index) u16 Renderer::BBoxRead(int index)
{ {
return static_cast<u16>(BBox::Get(index)); return static_cast<u16>(BBox::Get(index));
} }
void Renderer::BBoxWriteImpl(int index, u16 value) void Renderer::BBoxWrite(int index, u16 value)
{ {
BBox::Set(index, value); BBox::Set(index, value);
} }
void Renderer::BBoxFlushImpl() void Renderer::BBoxFlush()
{ {
BBox::Flush(); BBox::Flush();
} }

View File

@ -61,9 +61,9 @@ public:
void SetFullscreen(bool enable_fullscreen) override; void SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override; bool IsFullscreen() const override;
u16 BBoxReadImpl(int index) override; u16 BBoxRead(int index) override;
void BBoxWriteImpl(int index, u16 value) override; void BBoxWrite(int index, u16 value) override;
void BBoxFlushImpl() override; void BBoxFlush() override;
void Flush() override; void Flush() override;
void WaitForGPUIdle() override; void WaitForGPUIdle() override;

View File

@ -106,17 +106,17 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
return DXPipeline::Create(config, cache_data, cache_data_length); return DXPipeline::Create(config, cache_data, cache_data_length);
} }
u16 Renderer::BBoxReadImpl(int index) u16 Renderer::BBoxRead(int index)
{ {
return static_cast<u16>(m_bounding_box->Get(index)); return static_cast<u16>(m_bounding_box->Get(index));
} }
void Renderer::BBoxWriteImpl(int index, u16 value) void Renderer::BBoxWrite(int index, u16 value)
{ {
m_bounding_box->Set(index, value); m_bounding_box->Set(index, value);
} }
void Renderer::BBoxFlushImpl() void Renderer::BBoxFlush()
{ {
m_bounding_box->Flush(); m_bounding_box->Flush();
m_bounding_box->Invalidate(); m_bounding_box->Invalidate();

View File

@ -47,9 +47,9 @@ public:
const void* cache_data = nullptr, const void* cache_data = nullptr,
size_t cache_data_length = 0) override; size_t cache_data_length = 0) override;
u16 BBoxReadImpl(int index) override; u16 BBoxRead(int index) override;
void BBoxWriteImpl(int index, u16 value) override; void BBoxWrite(int index, u16 value) override;
void BBoxFlushImpl() override; void BBoxFlush() override;
void Flush() override; void Flush() override;
void WaitForGPUIdle() override; void WaitForGPUIdle() override;

View File

@ -34,8 +34,8 @@ public:
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; } u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; }
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {} void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
u16 BBoxReadImpl(int index) override { return 0; } u16 BBoxRead(int index) override { return 0; }
void BBoxWriteImpl(int index, u16 value) override {} void BBoxWrite(int index, u16 value) override {}
void ClearScreen(const MathUtil::Rectangle<int>& rc, bool colorEnable, bool alphaEnable, void ClearScreen(const MathUtil::Rectangle<int>& rc, bool colorEnable, bool alphaEnable,
bool zEnable, u32 color, u32 z) override bool zEnable, u32 color, u32 z) override

View File

@ -854,7 +854,7 @@ void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
glScissor(rc.left, rc.top, rc.GetWidth(), rc.GetHeight()); glScissor(rc.left, rc.top, rc.GetWidth(), rc.GetHeight());
} }
u16 Renderer::BBoxReadImpl(int index) u16 Renderer::BBoxRead(int index)
{ {
// swap 2 and 3 for top/bottom // swap 2 and 3 for top/bottom
if (index >= 2) if (index >= 2)
@ -870,7 +870,7 @@ u16 Renderer::BBoxReadImpl(int index)
return static_cast<u16>(value); return static_cast<u16>(value);
} }
void Renderer::BBoxWriteImpl(int index, u16 value) void Renderer::BBoxWrite(int index, u16 value)
{ {
s32 swapped_value = value; s32 swapped_value = value;
if (index >= 2) if (index >= 2)
@ -882,7 +882,7 @@ void Renderer::BBoxWriteImpl(int index, u16 value)
BoundingBox::Set(index, swapped_value); BoundingBox::Set(index, swapped_value);
} }
void Renderer::BBoxFlushImpl() void Renderer::BBoxFlush()
{ {
BoundingBox::Flush(); BoundingBox::Flush();
} }

View File

@ -126,9 +126,9 @@ public:
void BindBackbuffer(const ClearColor& clear_color = {}) override; void BindBackbuffer(const ClearColor& clear_color = {}) override;
void PresentBackbuffer() override; void PresentBackbuffer() override;
u16 BBoxReadImpl(int index) override; u16 BBoxRead(int index) override;
void BBoxWriteImpl(int index, u16 value) override; void BBoxWrite(int index, u16 value) override;
void BBoxFlushImpl() override; void BBoxFlush() override;
void BeginUtilityDrawing() override; void BeginUtilityDrawing() override;
void EndUtilityDrawing() override; void EndUtilityDrawing() override;

View File

@ -126,12 +126,12 @@ u32 SWRenderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
return value; return value;
} }
u16 SWRenderer::BBoxReadImpl(int index) u16 SWRenderer::BBoxRead(int index)
{ {
return BoundingBox::GetCoordinate(static_cast<BoundingBox::Coordinate>(index)); return BoundingBox::GetCoordinate(static_cast<BoundingBox::Coordinate>(index));
} }
void SWRenderer::BBoxWriteImpl(int index, u16 value) void SWRenderer::BBoxWrite(int index, u16 value)
{ {
BoundingBox::SetCoordinate(static_cast<BoundingBox::Coordinate>(index), value); BoundingBox::SetCoordinate(static_cast<BoundingBox::Coordinate>(index), value);
} }

View File

@ -39,8 +39,8 @@ public:
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {} void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
u16 BBoxReadImpl(int index) override; u16 BBoxRead(int index) override;
void BBoxWriteImpl(int index, u16 value) override; void BBoxWrite(int index, u16 value) override;
void RenderXFBToScreen(const MathUtil::Rectangle<int>& target_rc, void RenderXFBToScreen(const MathUtil::Rectangle<int>& target_rc,
const AbstractTexture* source_texture, const AbstractTexture* source_texture,

View File

@ -838,8 +838,10 @@ void Tev::Draw()
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_OUTPUT); EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_OUTPUT);
} }
BoundingBox::Update(static_cast<u16>(Position[0]), static_cast<u16>(Position[0]), // The GC/Wii GPU rasterizes in 2x2 pixel groups, so bounding box values will be rounded to the
static_cast<u16>(Position[1]), static_cast<u16>(Position[1])); // extents of these groups, rather than the exact pixel.
BoundingBox::Update(static_cast<u16>(Position[0] & ~1), static_cast<u16>(Position[0] | 1),
static_cast<u16>(Position[1] & ~1), static_cast<u16>(Position[1] | 1));
#if ALLOW_TEV_DUMPS #if ALLOW_TEV_DUMPS
if (g_ActiveConfig.bDumpTevStages) if (g_ActiveConfig.bDumpTevStages)

View File

@ -131,17 +131,17 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline)); StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline));
} }
u16 Renderer::BBoxReadImpl(int index) u16 Renderer::BBoxRead(int index)
{ {
return static_cast<u16>(m_bounding_box->Get(index)); return static_cast<u16>(m_bounding_box->Get(index));
} }
void Renderer::BBoxWriteImpl(int index, u16 value) void Renderer::BBoxWrite(int index, u16 value)
{ {
m_bounding_box->Set(index, value); m_bounding_box->Set(index, value);
} }
void Renderer::BBoxFlushImpl() void Renderer::BBoxFlush()
{ {
m_bounding_box->Flush(); m_bounding_box->Flush();
m_bounding_box->Invalidate(); m_bounding_box->Invalidate();

View File

@ -54,9 +54,9 @@ public:
SwapChain* GetSwapChain() const { return m_swap_chain.get(); } SwapChain* GetSwapChain() const { return m_swap_chain.get(); }
BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); } BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); }
u16 BBoxReadImpl(int index) override; u16 BBoxRead(int index) override;
void BBoxWriteImpl(int index, u16 value) override; void BBoxWrite(int index, u16 value) override;
void BBoxFlushImpl() override; void BBoxFlush() override;
void Flush() override; void Flush() override;
void WaitForGPUIdle() override; void WaitForGPUIdle() override;

View File

@ -492,19 +492,30 @@ void UpdateBoundingBox(float2 rawpos) {{
// such that width = right - left + 1. This has been verified on hardware. // such that width = right - left + 1. This has been verified on hardware.
int2 pos = iround(rawpos * cefbscale + offset); 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 #ifdef SUPPORTS_SUBGROUP_REDUCTION
if (CAN_USE_SUBGROUP_REDUCTION) {{ if (CAN_USE_SUBGROUP_REDUCTION) {{
int2 min_pos = IS_HELPER_INVOCATION ? int2(2147483647, 2147483647) : pos; int2 min_pos = IS_HELPER_INVOCATION ? int2(2147483647, 2147483647) : pos_tl;
int2 max_pos = IS_HELPER_INVOCATION ? int2(-2147483648, -2147483648) : pos; int2 max_pos = IS_HELPER_INVOCATION ? int2(-2147483648, -2147483648) : pos_br;
SUBGROUP_MIN(min_pos); SUBGROUP_MIN(min_pos);
SUBGROUP_MAX(max_pos); SUBGROUP_MAX(max_pos);
if (IS_FIRST_ACTIVE_INVOCATION) if (IS_FIRST_ACTIVE_INVOCATION)
UpdateBoundingBoxBuffer(min_pos, max_pos); UpdateBoundingBoxBuffer(min_pos, max_pos);
}} else {{ }} else {{
UpdateBoundingBoxBuffer(pos, pos); UpdateBoundingBoxBuffer(pos_tl, pos_br);
}} }}
#else #else
UpdateBoundingBoxBuffer(pos, pos); UpdateBoundingBoxBuffer(pos_tl, pos_br);
#endif #endif
}} }}

View File

@ -185,32 +185,6 @@ void Renderer::ReinterpretPixelData(EFBReinterpretType convtype)
g_framebuffer_manager->ReinterpretPixelData(convtype); g_framebuffer_manager->ReinterpretPixelData(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;
}
void Renderer::BBoxWrite(int index, u16 value)
{
BBoxWriteImpl(index, value);
}
void Renderer::BBoxFlush()
{
BBoxFlushImpl();
}
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{ {
if (type == EFBAccessType::PeekColor) if (type == EFBAccessType::PeekColor)

View File

@ -211,9 +211,9 @@ public:
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data); virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
virtual void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points); virtual void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points);
u16 BBoxRead(int index); virtual u16 BBoxRead(int index) = 0;
void BBoxWrite(int index, u16 value); virtual void BBoxWrite(int index, u16 value) = 0;
void BBoxFlush(); virtual void BBoxFlush() {}
virtual void Flush() {} virtual void Flush() {}
virtual void WaitForGPUIdle() {} virtual void WaitForGPUIdle() {}
@ -301,10 +301,6 @@ protected:
// Should be called with the ImGui lock held. // Should be called with the ImGui lock held.
void DrawImGui(); void DrawImGui();
virtual u16 BBoxReadImpl(int index) = 0;
virtual void BBoxWriteImpl(int index, u16 value) = 0;
virtual void BBoxFlushImpl() {}
AbstractFramebuffer* m_current_framebuffer = nullptr; AbstractFramebuffer* m_current_framebuffer = nullptr;
const AbstractPipeline* m_current_pipeline = nullptr; const AbstractPipeline* m_current_pipeline = nullptr;