summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2023-01-30 23:59:54 +1300
committerScott Mansell <phiren@gmail.com>2023-01-31 19:41:24 +1300
commit2a18b34a73f4f1bc798dab0a5eec46c222ec7429 (patch)
tree6fad80d43ff14bc4b673bf8f68cb937503783ed0 /Source
parent154cb4f722a9996a4134463e64c85c6bfa25d8bf (diff)
Wire up frame before/after events
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoCommon/AsyncRequests.cpp6
-rw-r--r--Source/Core/VideoCommon/BPStructs.cpp12
-rw-r--r--Source/Core/VideoCommon/Present.cpp123
-rw-r--r--Source/Core/VideoCommon/Present.h14
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp6
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.h1
6 files changed, 117 insertions, 45 deletions
diff --git a/Source/Core/VideoCommon/AsyncRequests.cpp b/Source/Core/VideoCommon/AsyncRequests.cpp
index 4ab52845f9..8c254d4e71 100644
--- a/Source/Core/VideoCommon/AsyncRequests.cpp
+++ b/Source/Core/VideoCommon/AsyncRequests.cpp
@@ -9,12 +9,14 @@
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/Fifo.h"
+#include "VideoCommon/Present.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoState.h"
+#include "VideoCommon/VideoEvents.h"
AsyncRequests AsyncRequests::s_singleton;
@@ -154,8 +156,8 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
break;
case Event::SWAP_EVENT:
- g_renderer->Swap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride,
- e.swap_event.fbHeight, e.time);
+ g_presenter->ViSwap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride,
+ e.swap_event.fbHeight, e.time);
break;
case Event::BBOX_READ:
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 8979031d3d..865d73dbed 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -31,6 +31,7 @@
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/PerfQueryBase.h"
+#include "VideoCommon/Present.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
@@ -42,6 +43,7 @@
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
+#include "VideoCommon/VideoEvents.h"
using namespace BPFunctions;
@@ -340,14 +342,16 @@ static void BPWritten(PixelShaderManager& pixel_shader_manager,
false, false, yScale, s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
bpmem.triggerEFBCopy.clamp_bottom, bpmem.copyfilter.GetCoefficients());
- // This stays in to signal end of a "frame"
- g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]);
+ // This is as closest as we have to an "end of the frame"
+ // It works 99% of the time.
+ AfterFrameEvent::Trigger();
+
if (g_ActiveConfig.bImmediateXFB)
{
// below div two to convert from bytes to pixels - it expects width, not stride
- g_renderer->Swap(destAddr, destStride / 2, destStride, height,
- Core::System::GetInstance().GetCoreTiming().GetTicks());
+ g_presenter->ImmediateSwap(destAddr, destStride / 2, destStride, height,
+ Core::System::GetInstance().GetCoreTiming().GetTicks());
}
else
{
diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp
index 159fe080af..69deb32e2c 100644
--- a/Source/Core/VideoCommon/Present.cpp
+++ b/Source/Core/VideoCommon/Present.cpp
@@ -16,6 +16,7 @@
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoConfig.h"
+#include "VideoCommon/VideoEvents.h"
std::unique_ptr<VideoCommon::Presenter> g_presenter;
@@ -60,6 +61,88 @@ bool Presenter::Initialize()
return true;
}
+bool Presenter::FetchXFB(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height)
+{
+ ReleaseXFBContentLock();
+
+ m_xfb_entry = g_texture_cache->GetXFBTexture(xfb_addr, fb_width, fb_height, fb_stride, &m_xfb_rect);
+
+ m_xfb_entry->AcquireContentLock();
+ if (m_last_xfb_id == m_xfb_entry->id)
+ return false;
+
+ m_last_xfb_id = m_xfb_entry->id;
+
+ return true;
+}
+
+void Presenter::ViSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks)
+{
+ bool unique = FetchXFB(xfb_addr, fb_width, fb_stride, fb_height);
+
+ PresentInfo present_info;
+ present_info.emulated_timestamp = ticks;
+ if (unique)
+ {
+ present_info.frame_count = m_frame_count++;
+ present_info.reason = PresentInfo::PresentReason::VideoInterface;
+ }
+ else
+ {
+ present_info.frame_count = m_frame_count - 1;
+ present_info.reason = PresentInfo::PresentReason::VideoInterfaceDuplicate;
+ }
+ present_info.present_count = m_present_count;
+
+ BeforePresentEvent::Trigger(present_info);
+
+ if (unique || !g_ActiveConfig.bSkipPresentingDuplicateXFBs)
+ {
+ Present();
+ ProcessFrameDumping(ticks);
+ }
+ else
+ {
+ g_gfx->Flush();
+ }
+}
+
+void Presenter::ImmediateSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks)
+{
+ FetchXFB(xfb_addr, fb_width, fb_stride, fb_height);
+
+ PresentInfo present_info;
+ present_info.emulated_timestamp = ticks;
+ present_info.frame_count = m_frame_count++;
+ present_info.reason = PresentInfo::PresentReason::Immediate;
+ present_info.present_count = m_present_count++;
+
+ Present();
+ ProcessFrameDumping(ticks);
+}
+
+void Presenter::ProcessFrameDumping(u64 ticks) const
+{
+ if (g_frame_dumper->IsFrameDumping())
+ {
+ MathUtil::Rectangle<int> target_rect;
+ if (!g_ActiveConfig.bInternalResolutionFrameDumps && !g_gfx->IsHeadless())
+ {
+ target_rect = GetTargetRectangle();
+ }
+ else
+ {
+ int width, height;
+ std::tie(width, height) =
+ CalculateOutputDimensions(m_xfb_rect.GetWidth(), m_xfb_rect.GetHeight());
+ target_rect = MathUtil::Rectangle<int>(0, 0, width, height);
+ }
+
+ g_frame_dumper->DumpCurrentFrame(m_xfb_entry->texture.get(), m_xfb_rect, target_rect, ticks,
+ m_frame_count);
+ }
+}
+
void Presenter::SetBackbuffer(int backbuffer_width, int backbuffer_height)
{
m_backbuffer_width = backbuffer_width;
@@ -80,8 +163,7 @@ void Presenter::CheckForConfigChanges(u32 changed_bits)
{
// Check for post-processing shader changes. Done up here as it doesn't affect anything outside
// the post-processor. Note that options are applied every frame, so no need to check those.
- if (m_post_processor &&
- m_post_processor->GetConfig()->GetShader() != g_ActiveConfig.sPostProcessingShader)
+ if (changed_bits & ConfigChangeBits::CONFIG_CHANGE_BIT_POST_PROCESSING_SHADER && m_post_processor)
{
// The existing shader must not be in use when it's destroyed
g_gfx->WaitForGPUIdle();
@@ -404,43 +486,10 @@ void Presenter::RenderXFBToScreen(const MathUtil::Rectangle<int>& target_rc,
}
}
-bool Presenter::SubmitXFB(RcTcacheEntry xfb_entry, MathUtil::Rectangle<int>& xfb_rect, u64 ticks,
- int frame_count)
-{
- m_xfb_entry = std::move(xfb_entry);
- m_xfb_rect = xfb_rect;
- bool is_duplicate_frame = m_last_xfb_id == m_xfb_entry->id;
- m_last_xfb_id = m_xfb_entry->id;
-
- if (!is_duplicate_frame || !g_ActiveConfig.bSkipPresentingDuplicateXFBs)
- {
- Present();
-
- if (g_frame_dumper->IsFrameDumping())
- {
- MathUtil::Rectangle<int> target_rect;
- if (!g_ActiveConfig.bInternalResolutionFrameDumps && !g_gfx->IsHeadless())
- {
- target_rect = GetTargetRectangle();
- }
- else
- {
- int width, height;
- std::tie(width, height) =
- CalculateOutputDimensions(m_xfb_rect.GetWidth(), m_xfb_rect.GetHeight());
- target_rect = MathUtil::Rectangle<int>(0, 0, width, height);
- }
-
- g_frame_dumper->DumpCurrentFrame(m_xfb_entry->texture.get(), m_xfb_rect, target_rect, ticks,
- frame_count);
- }
- }
-
- return is_duplicate_frame;
-}
-
void Presenter::Present()
{
+ m_present_count++;
+
if (g_gfx->IsHeadless() || (!m_onscreen_ui && !m_xfb_entry))
return;
diff --git a/Source/Core/VideoCommon/Present.h b/Source/Core/VideoCommon/Present.h
index 507c5ee424..4c870c93b0 100644
--- a/Source/Core/VideoCommon/Present.h
+++ b/Source/Core/VideoCommon/Present.h
@@ -31,8 +31,9 @@ public:
Presenter();
virtual ~Presenter();
- bool SubmitXFB(RcTcacheEntry xfb_entry, MathUtil::Rectangle<int>& xfb_rect, u64 ticks,
- int frame_count);
+ void ViSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
+ void ImmediateSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
+
void Present();
void ClearLastXfbId() { m_last_xfb_id = std::numeric_limits<u64>::max(); }
@@ -86,6 +87,12 @@ public:
const MathUtil::Rectangle<int>& GetTargetRectangle() const { return m_target_rectangle; }
private:
+ // Fetches the XFB texture from the texture cache.
+ // Returns true the contents have changed since last time
+ bool FetchXFB(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height);
+
+ void ProcessFrameDumping(u64 ticks) const;
+
std::tuple<int, int> CalculateOutputDimensions(int width, int height) const;
std::tuple<float, float> ApplyStandardAspectCrop(float width, float height) const;
std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height) const;
@@ -120,6 +127,9 @@ private:
std::unique_ptr<VideoCommon::PostProcessing> m_post_processor;
std::unique_ptr<VideoCommon::OnScreenUI> m_onscreen_ui;
+
+ u64 m_frame_count = 0;
+ u64 m_present_count = 0;
};
} // namespace VideoCommon
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index 959b080510..34fe374d25 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -417,6 +417,12 @@ void VertexManagerBase::Flush()
m_is_flushed = true;
+ if (m_draw_counter == 0)
+ {
+ // This is more or less the start of the Frame
+ BeforeFrameEvent::Trigger();
+ }
+
if (xfmem.numTexGen.numTexGens != bpmem.genMode.numtexgens ||
xfmem.numChan.numColorChans != bpmem.genMode.numcolchans)
{
diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h
index 3b8180c5d2..b2cb8b54bd 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.h
+++ b/Source/Core/VideoCommon/VertexManagerBase.h
@@ -13,6 +13,7 @@
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/RenderState.h"
#include "VideoCommon/ShaderCache.h"
+#include "VideoCommon/VideoEvents.h"
class DataReader;
class NativeVertexFormat;