Merge pull request #9773 from Techjar/bbox-default-values
VideoCommon: Add fallback handling for bounding box when disabled or unsupported
This commit is contained in:
commit
a3c89ac701
|
@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
constexpr u32 STATE_VERSION = 130; // Last changed in PR 9545
|
||||
constexpr u32 STATE_VERSION = 131; // Last changed in PR 9773
|
||||
|
||||
// Maps savestate versions to Dolphin versions.
|
||||
// Versions after 42 don't need to be added to this list,
|
||||
|
|
|
@ -264,17 +264,17 @@ void Renderer::UnbindTexture(const AbstractTexture* texture)
|
|||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
u16 Renderer::BBoxReadImpl(int index)
|
||||
{
|
||||
return static_cast<u16>(BBox::Get(index));
|
||||
}
|
||||
|
||||
void Renderer::BBoxWrite(int index, u16 value)
|
||||
void Renderer::BBoxWriteImpl(int index, u16 value)
|
||||
{
|
||||
BBox::Set(index, value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxFlush()
|
||||
void Renderer::BBoxFlushImpl()
|
||||
{
|
||||
BBox::Flush();
|
||||
}
|
||||
|
|
|
@ -61,9 +61,9 @@ public:
|
|||
void SetFullscreen(bool enable_fullscreen) override;
|
||||
bool IsFullscreen() const override;
|
||||
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
void BBoxFlush() override;
|
||||
u16 BBoxReadImpl(int index) override;
|
||||
void BBoxWriteImpl(int index, u16 value) override;
|
||||
void BBoxFlushImpl() override;
|
||||
|
||||
void Flush() override;
|
||||
void WaitForGPUIdle() override;
|
||||
|
|
|
@ -106,17 +106,17 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
|
|||
return DXPipeline::Create(config, cache_data, cache_data_length);
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
u16 Renderer::BBoxReadImpl(int index)
|
||||
{
|
||||
return static_cast<u16>(m_bounding_box->Get(index));
|
||||
}
|
||||
|
||||
void Renderer::BBoxWrite(int index, u16 value)
|
||||
void Renderer::BBoxWriteImpl(int index, u16 value)
|
||||
{
|
||||
m_bounding_box->Set(index, value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxFlush()
|
||||
void Renderer::BBoxFlushImpl()
|
||||
{
|
||||
m_bounding_box->Flush();
|
||||
m_bounding_box->Invalidate();
|
||||
|
|
|
@ -47,9 +47,9 @@ public:
|
|||
const void* cache_data = nullptr,
|
||||
size_t cache_data_length = 0) override;
|
||||
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
void BBoxFlush() override;
|
||||
u16 BBoxReadImpl(int index) override;
|
||||
void BBoxWriteImpl(int index, u16 value) override;
|
||||
void BBoxFlushImpl() override;
|
||||
|
||||
void Flush() override;
|
||||
void WaitForGPUIdle() override;
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
|
||||
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 {}
|
||||
u16 BBoxRead(int index) override { return 0; }
|
||||
void BBoxWrite(int index, u16 value) override {}
|
||||
u16 BBoxReadImpl(int index) override { return 0; }
|
||||
void BBoxWriteImpl(int index, u16 value) override {}
|
||||
|
||||
void ClearScreen(const MathUtil::Rectangle<int>& rc, bool colorEnable, bool alphaEnable,
|
||||
bool zEnable, u32 color, u32 z) override
|
||||
|
|
|
@ -854,7 +854,7 @@ void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
|
|||
glScissor(rc.left, rc.top, rc.GetWidth(), rc.GetHeight());
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
u16 Renderer::BBoxReadImpl(int index)
|
||||
{
|
||||
// swap 2 and 3 for top/bottom
|
||||
if (index >= 2)
|
||||
|
@ -870,7 +870,7 @@ u16 Renderer::BBoxRead(int index)
|
|||
return static_cast<u16>(value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxWrite(int index, u16 value)
|
||||
void Renderer::BBoxWriteImpl(int index, u16 value)
|
||||
{
|
||||
s32 swapped_value = value;
|
||||
if (index >= 2)
|
||||
|
@ -882,7 +882,7 @@ void Renderer::BBoxWrite(int index, u16 value)
|
|||
BoundingBox::Set(index, swapped_value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxFlush()
|
||||
void Renderer::BBoxFlushImpl()
|
||||
{
|
||||
BoundingBox::Flush();
|
||||
}
|
||||
|
|
|
@ -126,9 +126,9 @@ public:
|
|||
void BindBackbuffer(const ClearColor& clear_color = {}) override;
|
||||
void PresentBackbuffer() override;
|
||||
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
void BBoxFlush() override;
|
||||
u16 BBoxReadImpl(int index) override;
|
||||
void BBoxWriteImpl(int index, u16 value) override;
|
||||
void BBoxFlushImpl() override;
|
||||
|
||||
void BeginUtilityDrawing() override;
|
||||
void EndUtilityDrawing() override;
|
||||
|
|
|
@ -126,12 +126,12 @@ u32 SWRenderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
|
|||
return value;
|
||||
}
|
||||
|
||||
u16 SWRenderer::BBoxRead(int index)
|
||||
u16 SWRenderer::BBoxReadImpl(int index)
|
||||
{
|
||||
return BoundingBox::GetCoordinate(static_cast<BoundingBox::Coordinate>(index));
|
||||
}
|
||||
|
||||
void SWRenderer::BBoxWrite(int index, u16 value)
|
||||
void SWRenderer::BBoxWriteImpl(int index, u16 value)
|
||||
{
|
||||
BoundingBox::SetCoordinate(static_cast<BoundingBox::Coordinate>(index), value);
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ public:
|
|||
|
||||
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
|
||||
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
u16 BBoxReadImpl(int index) override;
|
||||
void BBoxWriteImpl(int index, u16 value) override;
|
||||
|
||||
void RenderXFBToScreen(const MathUtil::Rectangle<int>& target_rc,
|
||||
const AbstractTexture* source_texture,
|
||||
|
|
|
@ -131,17 +131,17 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
|
|||
StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline));
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
u16 Renderer::BBoxReadImpl(int index)
|
||||
{
|
||||
return static_cast<u16>(m_bounding_box->Get(index));
|
||||
}
|
||||
|
||||
void Renderer::BBoxWrite(int index, u16 value)
|
||||
void Renderer::BBoxWriteImpl(int index, u16 value)
|
||||
{
|
||||
m_bounding_box->Set(index, value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxFlush()
|
||||
void Renderer::BBoxFlushImpl()
|
||||
{
|
||||
m_bounding_box->Flush();
|
||||
m_bounding_box->Invalidate();
|
||||
|
|
|
@ -54,9 +54,9 @@ public:
|
|||
|
||||
SwapChain* GetSwapChain() const { return m_swap_chain.get(); }
|
||||
BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); }
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
void BBoxFlush() override;
|
||||
u16 BBoxReadImpl(int index) override;
|
||||
void BBoxWriteImpl(int index, u16 value) override;
|
||||
void BBoxFlushImpl() override;
|
||||
|
||||
void Flush() override;
|
||||
void WaitForGPUIdle() override;
|
||||
|
|
|
@ -445,11 +445,8 @@ static void BPWritten(const BPCmd& bp)
|
|||
const u8 offset = bp.address & 2;
|
||||
BoundingBox::Enable();
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsBBox && g_ActiveConfig.bBBoxEnable)
|
||||
{
|
||||
g_renderer->BBoxWrite(offset, bp.newvalue & 0x3ff);
|
||||
g_renderer->BBoxWrite(offset + 1, bp.newvalue >> 10);
|
||||
}
|
||||
g_renderer->BBoxWrite(offset, bp.newvalue & 0x3ff);
|
||||
g_renderer->BBoxWrite(offset + 1, bp.newvalue >> 10);
|
||||
}
|
||||
return;
|
||||
case BPMEM_TEXINVALIDATE:
|
||||
|
|
|
@ -185,6 +185,30 @@ void Renderer::ReinterpretPixelData(EFBReinterpretType convtype)
|
|||
g_framebuffer_manager->ReinterpretPixelData(convtype);
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
{
|
||||
if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
return m_bounding_box_fallback[index];
|
||||
|
||||
return BBoxReadImpl(index);
|
||||
}
|
||||
|
||||
void Renderer::BBoxWrite(int index, u16 value)
|
||||
{
|
||||
if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
{
|
||||
m_bounding_box_fallback[index] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
BBoxWriteImpl(index, value);
|
||||
}
|
||||
|
||||
void Renderer::BBoxFlush()
|
||||
{
|
||||
BBoxFlushImpl();
|
||||
}
|
||||
|
||||
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
{
|
||||
if (type == EFBAccessType::PeekColor)
|
||||
|
@ -1733,6 +1757,7 @@ void Renderer::DoState(PointerWrap& p)
|
|||
p.Do(m_last_xfb_width);
|
||||
p.Do(m_last_xfb_stride);
|
||||
p.Do(m_last_xfb_height);
|
||||
p.DoArray(m_bounding_box_fallback);
|
||||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
|
|
|
@ -211,9 +211,9 @@ public:
|
|||
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 u16 BBoxRead(int index) = 0;
|
||||
virtual void BBoxWrite(int index, u16 value) = 0;
|
||||
virtual void BBoxFlush() {}
|
||||
u16 BBoxRead(int index);
|
||||
void BBoxWrite(int index, u16 value);
|
||||
void BBoxFlush();
|
||||
|
||||
virtual void Flush() {}
|
||||
virtual void WaitForGPUIdle() {}
|
||||
|
@ -301,6 +301,10 @@ protected:
|
|||
// Should be called with the ImGui lock held.
|
||||
void DrawImGui();
|
||||
|
||||
virtual u16 BBoxReadImpl(int index) = 0;
|
||||
virtual void BBoxWriteImpl(int index, u16 value) = 0;
|
||||
virtual void BBoxFlushImpl() {}
|
||||
|
||||
AbstractFramebuffer* m_current_framebuffer = nullptr;
|
||||
const AbstractPipeline* m_current_pipeline = nullptr;
|
||||
|
||||
|
@ -390,6 +394,18 @@ private:
|
|||
u32 m_last_xfb_stride = 0;
|
||||
u32 m_last_xfb_height = 0;
|
||||
|
||||
// Nintendo's SDK seems to write "default" bounding box values before every draw (1023 0 1023 0
|
||||
// are the only values encountered so far, which happen to be the extents allowed by the BP
|
||||
// registers) to reset the registers for comparison in the pixel engine, and presumably to detect
|
||||
// whether GX has updated the registers with real values.
|
||||
//
|
||||
// We can store these values when Bounding Box emulation is disabled and return them on read,
|
||||
// which the game will interpret as "no pixels have been drawn"
|
||||
//
|
||||
// This produces much better results than just returning garbage, which can cause games like
|
||||
// Ultimate Spider-Man to crash
|
||||
std::array<u16, 4> m_bounding_box_fallback = {};
|
||||
|
||||
// NOTE: The methods below are called on the framedumping thread.
|
||||
void FrameDumpThreadFunc();
|
||||
bool StartFrameDumpToFFMPEG(const FrameDump::FrameData&);
|
||||
|
|
|
@ -168,10 +168,8 @@ u16 VideoBackendBase::Video_GetBoundingBox(int index)
|
|||
"for this game.");
|
||||
}
|
||||
warn_once = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
else if (!g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
{
|
||||
static bool warn_once = true;
|
||||
if (warn_once)
|
||||
|
@ -182,7 +180,6 @@ u16 VideoBackendBase::Video_GetBoundingBox(int index)
|
|||
"freezes while running this game.");
|
||||
}
|
||||
warn_once = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Fifo::SyncGPU(Fifo::SyncGPUReason::BBox);
|
||||
|
|
Loading…
Reference in New Issue