mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-19 23:20:21 +01:00
126 lines
3.3 KiB
C++
126 lines
3.3 KiB
C++
#include "stdafx.h"
|
|
#include "nv406e.h"
|
|
#include "nv47_sync.hpp"
|
|
|
|
#include "Emu/RSX/RSXThread.h"
|
|
|
|
#include "context_accessors.define.h"
|
|
|
|
namespace rsx
|
|
{
|
|
namespace nv406e
|
|
{
|
|
void set_reference(context* ctx, u32 /*reg*/, u32 arg)
|
|
{
|
|
RSX(ctx)->sync();
|
|
|
|
// Write ref+get (get will be written again with the same value at command end)
|
|
auto& dma = vm::_ref<RsxDmaControl>(RSX(ctx)->dma_address);
|
|
dma.get.release(RSX(ctx)->fifo_ctrl->get_pos());
|
|
dma.ref.store(arg);
|
|
}
|
|
|
|
void semaphore_acquire(context* ctx, u32 /*reg*/, u32 arg)
|
|
{
|
|
RSX(ctx)->sync_point_request.release(true);
|
|
const u32 addr = get_address(REGS(ctx)->semaphore_offset_406e(), REGS(ctx)->semaphore_context_dma_406e());
|
|
|
|
const auto& sema = vm::_ref<RsxSemaphore>(addr).val;
|
|
|
|
if (sema == arg)
|
|
{
|
|
// Flip semaphore doesnt need wake-up delay
|
|
if (addr != RSX(ctx)->label_addr + 0x10)
|
|
{
|
|
RSX(ctx)->flush_fifo();
|
|
RSX(ctx)->fifo_wake_delay(2);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
RSX(ctx)->flush_fifo();
|
|
}
|
|
|
|
u64 start = get_system_time();
|
|
u64 last_check_val = start;
|
|
|
|
while (sema != arg)
|
|
{
|
|
if (RSX(ctx)->test_stopped())
|
|
{
|
|
RSX(ctx)->state += cpu_flag::again;
|
|
return;
|
|
}
|
|
|
|
if (const auto tdr = static_cast<u64>(g_cfg.video.driver_recovery_timeout))
|
|
{
|
|
const u64 current = get_system_time();
|
|
|
|
if (current - last_check_val > 20'000)
|
|
{
|
|
// Suspicious amnount of time has passed
|
|
// External pause such as debuggers' pause or operating system sleep may have taken place
|
|
// Ignore it
|
|
start += current - last_check_val;
|
|
}
|
|
|
|
last_check_val = current;
|
|
|
|
if ((current - start) > tdr)
|
|
{
|
|
// If longer than driver timeout force exit
|
|
rsx_log.error("nv406e::semaphore_acquire has timed out. semaphore_address=0x%X", addr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
RSX(ctx)->cpu_wait({});
|
|
}
|
|
|
|
RSX(ctx)->fifo_wake_delay();
|
|
RSX(ctx)->performance_counters.idle_time += (get_system_time() - start);
|
|
}
|
|
|
|
void semaphore_release(context* ctx, u32 /*reg*/, u32 arg)
|
|
{
|
|
const u32 offset = REGS(ctx)->semaphore_offset_406e();
|
|
|
|
if (offset % 4)
|
|
{
|
|
rsx_log.warning("NV406E semaphore release is using unaligned semaphore, ignoring. (offset=0x%x)", offset);
|
|
return;
|
|
}
|
|
|
|
const u32 ctxt = REGS(ctx)->semaphore_context_dma_406e();
|
|
|
|
// By avoiding doing this on flip's semaphore release
|
|
// We allow last gcm's registers reset to occur in case of a crash
|
|
if (const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R);
|
|
!is_flip_sema)
|
|
{
|
|
RSX(ctx)->sync_point_request.release(true);
|
|
}
|
|
|
|
const u32 addr = get_address(offset, ctxt);
|
|
|
|
// TODO: Check if possible to write on reservations
|
|
if (RSX(ctx)->label_addr >> 28 != addr >> 28)
|
|
{
|
|
rsx_log.error("NV406E semaphore unexpected address. Please report to the developers. (offset=0x%x, addr=0x%x)", offset, addr);
|
|
RSX(ctx)->recover_fifo();
|
|
return;
|
|
}
|
|
|
|
if (addr == RSX(ctx)->device_addr + 0x30 && !arg)
|
|
{
|
|
// HW flip synchronization related, 1 is not written without display queue command (TODO: make it behave as real hw)
|
|
arg = 1;
|
|
}
|
|
|
|
util::write_gcm_label<false, true>(ctx, addr, arg);
|
|
}
|
|
}
|
|
}
|