Merge lle and hle vblank routines in a single thread
This commit is contained in:
parent
bc42cfaa6b
commit
1828ddfd6f
|
@ -72,7 +72,7 @@ Xbe::Xbe(const char *x_szFilename)
|
|||
// This is necessary because CxbxInitWindow internally calls g_AffinityPolicy->SetAffinityOther. If we are launched directly from the command line and the dashboard
|
||||
// cannot be opened, we will crash below because g_AffinityPolicy will be empty
|
||||
g_AffinityPolicy = AffinityPolicy::InitPolicy();
|
||||
CxbxInitWindow(false);
|
||||
CxbxInitWindow();
|
||||
|
||||
ULONG FatalErrorCode = FATAL_ERROR_XBE_DASH_GENERIC;
|
||||
|
||||
|
|
|
@ -229,7 +229,6 @@ static xbox::dword_xt *g_Xbox_D3DDevice; // TODO: This should b
|
|||
// Static Function(s)
|
||||
static DWORD WINAPI EmuRenderWindow(LPVOID);
|
||||
static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
static xbox::void_xt NTAPI EmuUpdateTickCount(xbox::PVOID Arg);
|
||||
static inline void EmuVerifyResourceIsRegistered(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTextureStage, DWORD dwSize);
|
||||
static void UpdateCurrentMSpFAndFPS(); // Used for benchmarking/fps count
|
||||
static void CxbxImpl_SetRenderTarget(xbox::X_D3DSurface *pRenderTarget, xbox::X_D3DSurface *pNewZStencil);
|
||||
|
@ -629,25 +628,13 @@ const char *D3DErrorString(HRESULT hResult)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void CxbxInitWindow(bool bFullInit)
|
||||
void CxbxInitWindow()
|
||||
{
|
||||
g_EmuShared->GetVideoSettings(&g_XBVideo);
|
||||
|
||||
if(g_XBVideo.bFullScreen)
|
||||
CxbxKrnl_hEmuParent = NULL;
|
||||
|
||||
// create timing thread
|
||||
if (bFullInit && !bLLE_GPU)
|
||||
{
|
||||
xbox::HANDLE hThread;
|
||||
xbox::PsCreateSystemThread(&hThread, xbox::zeroptr, EmuUpdateTickCount, xbox::zeroptr, FALSE);
|
||||
// We set the priority of this thread a bit higher, to assure reliable timing :
|
||||
auto nativeHandle = GetNativeHandle(hThread);
|
||||
assert(nativeHandle);
|
||||
SetThreadPriority(*nativeHandle, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
g_AffinityPolicy->SetAffinityOther(*nativeHandle);
|
||||
}
|
||||
|
||||
/* TODO : Port this Dxbx code :
|
||||
// create vblank handling thread
|
||||
{
|
||||
|
@ -1930,47 +1917,33 @@ std::chrono::steady_clock::time_point GetNextVBlankTime()
|
|||
return steady_clock::now() + duration_cast<steady_clock::duration>(ms);
|
||||
}
|
||||
|
||||
// timing thread procedure
|
||||
static xbox::void_xt NTAPI EmuUpdateTickCount(xbox::PVOID Arg)
|
||||
void hle_vblank()
|
||||
{
|
||||
CxbxSetThreadName("Cxbx Timing Thread");
|
||||
// Note: This whole code block can be removed once NV2A interrupts are implemented
|
||||
// And Both Swap and Present can be ran unpatched
|
||||
// Once that is in place, MiniPort + Direct3D will handle this on it's own!
|
||||
// Increment the VBlank Counter and Wake all threads there were waiting for the VBlank to occur
|
||||
std::unique_lock<std::mutex> lk(g_VBConditionMutex);
|
||||
g_Xbox_VBlankData.VBlank++;
|
||||
g_VBConditionVariable.notify_all();
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Timing thread is running.");
|
||||
// TODO: Fixme. This may not be right...
|
||||
g_Xbox_SwapData.SwapVBlank = 1;
|
||||
|
||||
auto nextVBlankTime = GetNextVBlankTime();
|
||||
|
||||
while(true)
|
||||
{
|
||||
// Wait for VBlank
|
||||
// Note: This whole code block can be removed once NV2A interrupts are implemented
|
||||
// And Both Swap and Present can be ran unpatched
|
||||
// Once that is in place, MiniPort + Direct3D will handle this on it's own!
|
||||
SleepPrecise(nextVBlankTime);
|
||||
nextVBlankTime = GetNextVBlankTime();
|
||||
|
||||
// Increment the VBlank Counter and Wake all threads there were waiting for the VBlank to occur
|
||||
std::unique_lock<std::mutex> lk(g_VBConditionMutex);
|
||||
g_Xbox_VBlankData.VBlank++;
|
||||
g_VBConditionVariable.notify_all();
|
||||
|
||||
// TODO: Fixme. This may not be right...
|
||||
g_Xbox_SwapData.SwapVBlank = 1;
|
||||
|
||||
if(g_pXbox_VerticalBlankCallback != xbox::zeroptr)
|
||||
{
|
||||
g_pXbox_VerticalBlankCallback(&g_Xbox_VBlankData);
|
||||
}
|
||||
|
||||
g_Xbox_VBlankData.Swap = 0;
|
||||
|
||||
// TODO: This can't be accurate...
|
||||
g_Xbox_SwapData.TimeUntilSwapVBlank = 0;
|
||||
|
||||
// TODO: Recalculate this for PAL version if necessary.
|
||||
// Also, we should check the D3DPRESENT_INTERVAL value for accurracy.
|
||||
// g_Xbox_SwapData.TimeBetweenSwapVBlanks = 1/60;
|
||||
g_Xbox_SwapData.TimeBetweenSwapVBlanks = 0;
|
||||
if (g_pXbox_VerticalBlankCallback != xbox::zeroptr)
|
||||
{
|
||||
g_pXbox_VerticalBlankCallback(&g_Xbox_VBlankData);
|
||||
}
|
||||
|
||||
g_Xbox_VBlankData.Swap = 0;
|
||||
|
||||
// TODO: This can't be accurate...
|
||||
g_Xbox_SwapData.TimeUntilSwapVBlank = 0;
|
||||
|
||||
// TODO: Recalculate this for PAL version if necessary.
|
||||
// Also, we should check the D3DPRESENT_INTERVAL value for accurracy.
|
||||
// g_Xbox_SwapData.TimeBetweenSwapVBlanks = 1/60;
|
||||
g_Xbox_SwapData.TimeBetweenSwapVBlanks = 0;
|
||||
}
|
||||
|
||||
void UpdateDepthStencilFlags(IDirect3DSurface *pDepthStencilSurface)
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
void LookupTrampolinesD3D();
|
||||
|
||||
// initialize render window
|
||||
extern void CxbxInitWindow(bool bFullInit);
|
||||
extern void CxbxInitWindow();
|
||||
|
||||
void CxbxUpdateNativeD3DResources();
|
||||
|
||||
|
|
|
@ -1362,7 +1362,7 @@ static void CxbxrKrnlInitHacks()
|
|||
|
||||
// initialize graphics
|
||||
EmuLogInit(LOG_LEVEL::DEBUG, "Initializing render window.");
|
||||
CxbxInitWindow(true);
|
||||
CxbxInitWindow();
|
||||
|
||||
// Now process the boot flags to see if there are any special conditions to handle
|
||||
if (BootFlags & BOOT_EJECT_PENDING) {} // TODO
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
#include "core\kernel\init\CxbxKrnl.h" // For XBOX_MEMORY_SIZE, DWORD, etc
|
||||
#include "core\kernel\support\Emu.h"
|
||||
#include "core\kernel\support\NativeHandle.h"
|
||||
#include "core\kernel\exports\EmuKrnl.h"
|
||||
#include <backends/imgui_impl_win32.h>
|
||||
#include <backends/imgui_impl_opengl3.h>
|
||||
|
@ -58,6 +59,7 @@
|
|||
#include "core\hle\Intercept.hpp"
|
||||
#include "common/win32/Threads.h"
|
||||
#include "Logging.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include "vga.h"
|
||||
#include "nv2a.h" // For NV2AState
|
||||
|
@ -319,8 +321,8 @@ const NV2ABlockInfo* EmuNV2A_Block(xbox::addr_xt addr)
|
|||
|
||||
// HACK: Until we implement VGA/proper interrupt generation
|
||||
// we simulate VBLANK by calling the interrupt at 60Hz
|
||||
std::thread vblank_thread;
|
||||
extern std::chrono::steady_clock::time_point GetNextVBlankTime();
|
||||
extern void hle_vblank();
|
||||
|
||||
void _check_gl_reset()
|
||||
{
|
||||
|
@ -1097,25 +1099,37 @@ void NV2ADevice::UpdateHostDisplay(NV2AState *d)
|
|||
}
|
||||
|
||||
// TODO: Fix this properly
|
||||
static void nv2a_vblank_thread(NV2AState *d)
|
||||
template<bool should_update_hle>
|
||||
static xbox::void_xt NTAPI nv2a_vblank_thread(xbox::PVOID arg)
|
||||
{
|
||||
g_AffinityPolicy->SetAffinityOther();
|
||||
CxbxSetThreadName("Cxbx NV2A VBLANK");
|
||||
NV2AState *d = static_cast<NV2AState *>(arg);
|
||||
|
||||
if constexpr (should_update_hle) {
|
||||
CxbxSetThreadName("Cxbxr NV2A and HLE VBLANK");
|
||||
}
|
||||
else {
|
||||
g_AffinityPolicy->SetAffinityOther();
|
||||
CxbxSetThreadName("Cxbxr NV2A VBLANK");
|
||||
}
|
||||
|
||||
auto nextVBlankTime = GetNextVBlankTime();
|
||||
|
||||
while (!d->exiting) {
|
||||
// Handle VBlank
|
||||
if (std::chrono::steady_clock::now() > nextVBlankTime) {
|
||||
d->pcrtc.pending_interrupts |= NV_PCRTC_INTR_0_VBLANK;
|
||||
update_irq(d);
|
||||
nextVBlankTime = GetNextVBlankTime();
|
||||
while (!d->exiting) [[unlikely]] {
|
||||
|
||||
// TODO: We should swap here for the purposes of supporting overlays + direct framebuffer access
|
||||
// But it causes crashes on AMD hardware for reasons currently unknown...
|
||||
//NV2ADevice::UpdateHostDisplay(d);
|
||||
// Wait for VBlank
|
||||
SleepPrecise(nextVBlankTime);
|
||||
nextVBlankTime = GetNextVBlankTime();
|
||||
|
||||
d->pcrtc.pending_interrupts |= NV_PCRTC_INTR_0_VBLANK;
|
||||
update_irq(d);
|
||||
|
||||
// TODO: We should swap here for the purposes of supporting overlays + direct framebuffer access
|
||||
// But it causes crashes on AMD hardware for reasons currently unknown...
|
||||
//NV2ADevice::UpdateHostDisplay(d);
|
||||
|
||||
if constexpr (should_update_hle) {
|
||||
hle_vblank();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1202,7 +1216,20 @@ void NV2ADevice::Init()
|
|||
pvideo_init(d);
|
||||
}
|
||||
|
||||
vblank_thread = std::thread(nv2a_vblank_thread, d);
|
||||
|
||||
if (bLLE_GPU) {
|
||||
xbox::HANDLE hThread;
|
||||
xbox::PsCreateSystemThread(&hThread, xbox::zeroptr, nv2a_vblank_thread<false>, d, FALSE);
|
||||
d->vblank_thread = *GetNativeHandle(hThread);
|
||||
}
|
||||
else {
|
||||
xbox::HANDLE hThread;
|
||||
xbox::PsCreateSystemThread(&hThread, xbox::zeroptr, nv2a_vblank_thread<true>, d, FALSE);
|
||||
// We set the priority of this thread a bit higher, to assure reliable timing
|
||||
d->vblank_thread = *GetNativeHandle(hThread);
|
||||
SetThreadPriority(d->vblank_thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
g_AffinityPolicy->SetAffinityOther(d->vblank_thread);
|
||||
}
|
||||
|
||||
qemu_mutex_init(&d->pfifo.pfifo_lock);
|
||||
qemu_cond_init(&d->pfifo.puller_cond);
|
||||
|
@ -1227,9 +1254,9 @@ void NV2ADevice::Reset()
|
|||
qemu_cond_broadcast(&d->pfifo.pusher_cond);
|
||||
d->pfifo.puller_thread.join();
|
||||
d->pfifo.pusher_thread.join();
|
||||
qemu_mutex_destroy(&d->pfifo.pfifo_lock); // Cbxbx addition
|
||||
qemu_mutex_destroy(&d->pfifo.pfifo_lock); // Cxbxr addition
|
||||
if (d->pgraph.opengl_enabled) {
|
||||
vblank_thread.join();
|
||||
WaitForSingleObject(d->vblank_thread, INFINITE);
|
||||
pvideo_destroy(d);
|
||||
}
|
||||
|
||||
|
|
|
@ -357,6 +357,7 @@ typedef struct OverlayState {
|
|||
} OverlayState;
|
||||
|
||||
typedef struct NV2AState {
|
||||
HANDLE vblank_thread;
|
||||
// PCIDevice dev;
|
||||
// qemu_irq irq;
|
||||
bool exiting;
|
||||
|
|
Loading…
Reference in New Issue