summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authordegasus <wickmarkus@web.de>2015-01-31 11:38:23 +0100
committerdegasus <wickmarkus@web.de>2015-02-22 08:41:15 +0100
commitbc248f8941ae5f24e651d5bf029740bc96c3df89 (patch)
treec2b209edda05a9f11f32dbfbb8549e0bffcd9616 /Source/Core
parent860c889454635c0f4f7cf601f8ec77c7b81c19cd (diff)
VideoCommon: use a new async event system for efb access
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoCommon/AsyncRequests.cpp88
-rw-r--r--Source/Core/VideoCommon/AsyncRequests.h71
-rw-r--r--Source/Core/VideoCommon/CMakeLists.txt3
-rw-r--r--Source/Core/VideoCommon/Fifo.cpp6
-rw-r--r--Source/Core/VideoCommon/MainBase.cpp77
-rw-r--r--Source/Core/VideoCommon/MainBase.h1
-rw-r--r--Source/Core/VideoCommon/RenderBase.cpp1
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp2
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj2
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj.filters6
10 files changed, 200 insertions, 57 deletions
diff --git a/Source/Core/VideoCommon/AsyncRequests.cpp b/Source/Core/VideoCommon/AsyncRequests.cpp
new file mode 100644
index 0000000000..dce56c0d7b
--- /dev/null
+++ b/Source/Core/VideoCommon/AsyncRequests.cpp
@@ -0,0 +1,88 @@
+#include "VideoCommon/AsyncRequests.h"
+#include "VideoCommon/RenderBase.h"
+
+AsyncRequests AsyncRequests::s_singleton;
+
+AsyncRequests::AsyncRequests()
+: m_enable(false)
+{
+}
+
+void AsyncRequests::PullEventsInternal()
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_empty.store(true);
+
+ while (!m_queue.empty())
+ {
+ const Event& e = m_queue.front();
+
+ lock.unlock();
+ HandleEvent(e);
+ lock.lock();
+
+ m_queue.pop();
+ }
+
+ if (m_wake_me_up_again)
+ {
+ m_wake_me_up_again = false;
+ m_cond.notify_all();
+ }
+}
+
+void AsyncRequests::PushEvent(const AsyncRequests::Event& event, bool blocking)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_empty.store(false);
+ m_wake_me_up_again |= blocking;
+
+ if (!m_enable)
+ return;
+
+ m_queue.push(event);
+
+ if (blocking)
+ {
+ m_cond.wait(lock, [this]{return m_queue.empty();});
+ }
+}
+
+void AsyncRequests::SetEnable(bool enable)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_enable = enable;
+
+ if (!enable)
+ {
+ // flush the queue on disabling
+ while (!m_queue.empty())
+ m_queue.pop();
+ if (m_wake_me_up_again)
+ m_cond.notify_all();
+ }
+}
+
+void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
+{
+ switch (e.type)
+ {
+ case Event::EFB_POKE_COLOR:
+ g_renderer->AccessEFB(POKE_COLOR, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
+ break;
+
+ case Event::EFB_POKE_Z:
+ g_renderer->AccessEFB(POKE_Z, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
+ break;
+
+ case Event::EFB_PEEK_COLOR:
+ *e.efb_peek.data = g_renderer->AccessEFB(PEEK_COLOR, e.efb_peek.x, e.efb_peek.y, 0);
+ break;
+
+ case Event::EFB_PEEK_Z:
+ *e.efb_peek.data = g_renderer->AccessEFB(PEEK_Z, e.efb_peek.x, e.efb_peek.y, 0);
+ break;
+
+ }
+}
+
diff --git a/Source/Core/VideoCommon/AsyncRequests.h b/Source/Core/VideoCommon/AsyncRequests.h
new file mode 100644
index 0000000000..d3cfece7eb
--- /dev/null
+++ b/Source/Core/VideoCommon/AsyncRequests.h
@@ -0,0 +1,71 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+
+#include "Common/CommonTypes.h"
+
+class AsyncRequests
+{
+public:
+ struct Event
+ {
+ enum Type
+ {
+ EFB_POKE_COLOR,
+ EFB_POKE_Z,
+ EFB_PEEK_COLOR,
+ EFB_PEEK_Z,
+ } type;
+ u64 time;
+
+ union
+ {
+ struct
+ {
+ u16 x;
+ u16 y;
+ u32 data;
+ } efb_poke;
+
+ struct
+ {
+ u16 x;
+ u16 y;
+ u32* data;
+ } efb_peek;
+ };
+ };
+
+ AsyncRequests();
+
+ void PullEvents()
+ {
+ if (!m_empty.load())
+ PullEventsInternal();
+ }
+ void PushEvent(const Event& event, bool blocking = false);
+ void SetEnable(bool enable);
+
+ static AsyncRequests* GetInstance() { return &s_singleton; }
+
+private:
+ void PullEventsInternal();
+ void HandleEvent(const Event& e);
+
+ static AsyncRequests s_singleton;
+
+ std::atomic<bool> m_empty;
+ std::queue<Event> m_queue;
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+
+ bool m_wake_me_up_again;
+ bool m_enable;
+};
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 4e6dd8a6b6..f3ef98a741 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -1,4 +1,5 @@
-set(SRCS BoundingBox.cpp
+set(SRCS AsyncRequests.cpp
+ BoundingBox.cpp
BPFunctions.cpp
BPMemory.cpp
BPStructs.cpp
diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp
index 9da3583a9d..b8f4002d4d 100644
--- a/Source/Core/VideoCommon/Fifo.cpp
+++ b/Source/Core/VideoCommon/Fifo.cpp
@@ -15,6 +15,7 @@
#include "Core/NetPlayProto.h"
#include "Core/HW/Memmap.h"
+#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/CPMemory.h"
#include "VideoCommon/DataReader.h"
@@ -282,11 +283,14 @@ void RunGpuLoop()
// This allows a system that we are maxing out in dual core mode to do other things
bool yield_cpu = cpu_info.num_cores <= 2;
+ AsyncRequests::GetInstance()->SetEnable(true);
+
while (GpuRunningState)
{
g_video_backend->PeekMessages();
VideoFifo_CheckAsyncRequest();
+ AsyncRequests::GetInstance()->PullEvents();
if (g_use_deterministic_gpu_thread)
{
// All the fifo/CP stuff is on the CPU. We just need to run the opcode decoder.
@@ -349,6 +353,7 @@ void RunGpuLoop()
// If we don't, s_swapRequested or s_efbAccessRequested won't be set to false
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
VideoFifo_CheckAsyncRequest();
+ AsyncRequests::GetInstance()->PullEvents();
CommandProcessor::isPossibleWaitingSetDrawDone = false;
}
@@ -377,6 +382,7 @@ void RunGpuLoop()
}
// wake up SyncGPU if we were interrupted
s_video_buffer_cond.notify_all();
+ AsyncRequests::GetInstance()->SetEnable(false);
}
diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp
index b5c6cdebf9..47eab7d941 100644
--- a/Source/Core/VideoCommon/MainBase.cpp
+++ b/Source/Core/VideoCommon/MainBase.cpp
@@ -1,6 +1,7 @@
#include "Common/Event.h"
#include "Core/ConfigManager.h"
+#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/BPStructs.h"
#include "VideoCommon/CommandProcessor.h"
@@ -20,8 +21,6 @@ bool s_BackendInitialized = false;
Common::Flag s_swapRequested;
static Common::Flag s_FifoShuttingDown;
-static Common::Flag s_efbAccessRequested;
-static Common::Event s_efbAccessReadyEvent;
static Common::Flag s_perfQueryRequested;
static Common::Event s_perfQueryReadyEvent;
@@ -39,16 +38,6 @@ static volatile struct
u32 fbHeight;
} s_beginFieldArgs;
-static struct
-{
- EFBAccessType type;
- u32 x;
- u32 y;
- u32 Data;
-} s_accessEFBArgs;
-
-static u32 s_AccessEFBResult = 0;
-
void VideoBackendHardware::EmuStateChange(EMUSTATE_CHANGE newState)
{
EmulatorState((newState == EMUSTATE_CHANGE_PLAY) ? true : false);
@@ -64,7 +53,6 @@ void VideoBackendHardware::Video_ExitLoop()
{
ExitGpuLoop();
s_FifoShuttingDown.Set();
- s_efbAccessReadyEvent.Set();
s_perfQueryReadyEvent.Set();
}
@@ -152,44 +140,36 @@ bool VideoBackendHardware::Video_Screenshot(const std::string& filename)
return true;
}
-void VideoFifo_CheckEFBAccess()
+u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
{
- if (s_efbAccessRequested.IsSet())
+ if (!g_ActiveConfig.bEFBAccessEnable)
{
- s_AccessEFBResult = g_renderer->AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y, s_accessEFBArgs.Data);
- s_efbAccessRequested.Clear();
- s_efbAccessReadyEvent.Set();
+ return 0;
}
-}
-u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
-{
- if (s_BackendInitialized && g_ActiveConfig.bEFBAccessEnable)
+ if (type == POKE_COLOR || type == POKE_Z)
{
- SyncGPU(SYNC_GPU_EFB_POKE);
-
- s_accessEFBArgs.type = type;
- s_accessEFBArgs.x = x;
- s_accessEFBArgs.y = y;
- s_accessEFBArgs.Data = InputData;
-
- s_efbAccessRequested.Set();
-
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
- {
- s_efbAccessReadyEvent.Reset();
- if (s_FifoShuttingDown.IsSet())
- return 0;
- s_efbAccessRequested.Set();
- s_efbAccessReadyEvent.Wait();
- }
- else
- VideoFifo_CheckEFBAccess();
-
- return s_AccessEFBResult;
+ AsyncRequests::Event e;
+ e.type = type == POKE_COLOR ? AsyncRequests::Event::EFB_POKE_COLOR : AsyncRequests::Event::EFB_POKE_Z;
+ e.time = 0;
+ e.efb_poke.data = InputData;
+ e.efb_poke.x = x;
+ e.efb_poke.y = y;
+ AsyncRequests::GetInstance()->PushEvent(e, 0);
+ return 0;
+ }
+ else
+ {
+ AsyncRequests::Event e;
+ u32 result;
+ e.type = type == PEEK_COLOR ? AsyncRequests::Event::EFB_PEEK_COLOR : AsyncRequests::Event::EFB_PEEK_Z;
+ e.time = 0;
+ e.efb_peek.x = x;
+ e.efb_peek.y = y;
+ e.efb_peek.data = &result;
+ AsyncRequests::GetInstance()->PushEvent(e, 1);
+ return result;
}
-
- return 0;
}
static void VideoFifo_CheckPerfQueryRequest()
@@ -267,12 +247,9 @@ void VideoBackendHardware::InitializeShared()
VideoCommon_Init();
s_swapRequested.Clear();
- s_efbAccessRequested.Clear();
s_perfQueryRequested.Clear();
s_FifoShuttingDown.Clear();
memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs));
- memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs));
- s_AccessEFBResult = 0;
m_invalid = false;
}
@@ -292,10 +269,7 @@ void VideoBackendHardware::DoState(PointerWrap& p)
p.DoMarker("VideoCommon");
p.Do(s_swapRequested);
- p.Do(s_efbAccessRequested);
p.Do(s_beginFieldArgs);
- p.Do(s_accessEFBArgs);
- p.Do(s_AccessEFBResult);
p.DoMarker("VideoBackendHardware");
// Refresh state.
@@ -335,7 +309,6 @@ void VideoBackendHardware::RunLoop(bool enable)
void VideoFifo_CheckAsyncRequest()
{
VideoFifo_CheckSwapRequest();
- VideoFifo_CheckEFBAccess();
VideoFifo_CheckPerfQueryRequest();
VideoFifo_CheckBBoxRequest();
}
diff --git a/Source/Core/VideoCommon/MainBase.h b/Source/Core/VideoCommon/MainBase.h
index bcef8024ec..b8eebf37a0 100644
--- a/Source/Core/VideoCommon/MainBase.h
+++ b/Source/Core/VideoCommon/MainBase.h
@@ -6,5 +6,4 @@
extern bool s_BackendInitialized;
extern Common::Flag s_swapRequested;
-void VideoFifo_CheckEFBAccess();
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp
index 3e95eca5cc..cb9be880e0 100644
--- a/Source/Core/VideoCommon/RenderBase.cpp
+++ b/Source/Core/VideoCommon/RenderBase.cpp
@@ -116,7 +116,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidt
if (!fbWidth || !fbHeight)
return;
- VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
XFBWrited = true;
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index bf7800cc9a..520654448f 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -166,8 +166,6 @@ void VertexManager::Flush()
// loading a state will invalidate BP, so check for it
g_video_backend->CheckInvalidState();
- VideoFifo_CheckEFBAccess();
-
#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfmem.numTexGen.numTexGens,
xfmem.numChan.numColorChans, xfmem.dualTexTrans.enabled, bpmem.ztex2.op,
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index 649cd5095e..ff56a97703 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -35,6 +35,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
+ <ClCompile Include="AsyncRequests.cpp" />
<ClCompile Include="AVIDump.cpp" />
<ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="BPFunctions.cpp" />
@@ -84,6 +85,7 @@
<ClCompile Include="XFStructs.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="AsyncRequests.h" />
<ClInclude Include="AVIDump.h" />
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="BPFunctions.h" />
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index eca9287439..1998fce1cc 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -146,6 +146,9 @@
<ClCompile Include="TextureDecoder_x64.cpp">
<Filter>Decoding</Filter>
</ClCompile>
+ <ClCompile Include="AsyncRequests.cpp">
+ <Filter>Util</Filter>
+ </ClCompile>
<ClCompile Include="BoundingBox.cpp">
<Filter>Util</Filter>
</ClCompile>
@@ -290,6 +293,9 @@
<ClInclude Include="VertexLoaderUtils.h">
<Filter>Vertex Loading</Filter>
</ClInclude>
+ <ClInclude Include="AsyncRequests.h">
+ <Filter>Util</Filter>
+ </ClInclude>
<ClInclude Include="BoundingBox.h">
<Filter>Util</Filter>
</ClInclude>