rsx: Cleanup changes for the flip patch

This commit is contained in:
kd-11 2018-09-22 10:51:48 +03:00 committed by kd-11
parent 699eadc84f
commit a3d44b5e1f
9 changed files with 112 additions and 60 deletions

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/Memory/vm.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
@ -13,7 +13,8 @@ LOG_CHANNEL(sys_rsx);
extern u64 get_timebased_time();
u64 rsxTimeStamp() {
u64 rsxTimeStamp()
{
return get_timebased_time();
}
@ -178,8 +179,8 @@ s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
{
sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
if (!size || io & 0xFFFFF || ea & 0xFFFFF || size & 0xFFFFF
|| rsx::get_current_renderer()->main_mem_size < io + size)
if (!size || io & 0xFFFFF || ea & 0xFFFFF || size & 0xFFFFF ||
rsx::get_current_renderer()->main_mem_size < io + size)
{
return CELL_EINVAL;
}
@ -323,6 +324,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
if (a3 == 1)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 6), 0);
break;
case 0x104: // Display buffer
{
u8 id = a3 & 0xFF;
@ -340,11 +342,13 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
render->display_buffers_count = std::max((u32)id + 1, render->display_buffers_count);
}
break;
case 0x105: // destroy buffer?
break;
case 0x106: // ? (Used by cellGcmInitPerfMon)
break;
case 0x108: // cellGcmSetSecondVFrequency
// a4 == 3, CELL_GCM_DISPLAY_FREQUENCY_59_94HZ
// a4 == 2, CELL_GCM_DISPLAY_FREQUENCY_SCANOUT
@ -352,10 +356,12 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
// Note: Scanout/59_94 is ignored currently as we report refresh rate of 59_94hz as it is, so the difference doesnt matter
render->enable_second_vhandler.store(a4 != 4);
break;
case 0x10a: // ? Involved in managing flip status through cellGcmResetFlipStatus
{
if (a3 > 7)
return -17;
u32 flipStatus = driverInfo.head[a3].flipFlags;
flipStatus = (flipStatus & a4) | a5;
driverInfo.head[a3].flipFlags = flipStatus;
@ -417,6 +423,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
case 0x302: // something with zcull
break;
case 0x600: // Framebuffer setup
break;
@ -429,14 +436,32 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
case 0x603: // Framebuffer close
break;
case 0xFEC: // hack: flip event notification
// we only ever use head 1 for now
driverInfo.head[1].flipFlags |= 0x80000000;
driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
driverInfo.head[1].flipBufferId = (u32)a3;
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
vm::_ref<u32>(render->label_addr + 0x10) = 0;
//if (a3 == 0)
// sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0);
//if (a3 == 1)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 4), 0);
break;
case 0xFED: // hack: vblank command
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
driverInfo.head[a3].vBlankCount++;
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 1), 0);
if (render->enable_second_vhandler)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 11), 0); // second vhandler
break;
case 0xFEF: // hack: user command
// 'custom' invalid package id for now
// as i think we need custom lv1 interrupts to handle this accurately
@ -444,6 +469,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
driverInfo.userCmdParam = a4;
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 7), 0);
break;
default:
return CELL_EINVAL;
}
@ -505,28 +531,4 @@ s32 sys_rsx_attribute(u32 packageId, u32 a2, u32 a3, u32 a4, u32 a5)
sys_rsx.warning("sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", packageId, a2, a3, a4, a5);
return CELL_OK;
}
void sys_rsx_flip_event(u32 buffer)
{
auto m_sysrsx = fxm::get<SysRsxConfig>();
if (!m_sysrsx)
return;
auto &driverInfo = vm::_ref<RsxDriverInfo>(m_sysrsx->driverInfo);
const auto render = rsx::get_current_renderer();
// we only ever use head 1 for now
driverInfo.head[1].flipFlags |= 0x80000000;
driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
driverInfo.head[1].flipBufferId = buffer;
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
vm::_ref<u32>(render->label_addr + 0x10) = 0;
//if (a3 == 0)
// sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0);
//if (a3 == 1)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 4), 0);
}
}

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
struct RsxDriverInfo
{
@ -119,6 +119,3 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
s32 sys_rsx_device_map(vm::ptr<u64> dev_addr, vm::ptr<u64> a2, u32 dev_id);
s32 sys_rsx_device_unmap(u32 dev_id);
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
// Custom 'RSX Events', not lv2 syscalls
void sys_rsx_flip_event(u32 buffer);

View File

@ -1722,9 +1722,10 @@ void GLGSRender::do_local_task(rsx::FIFO_state state)
if (m_overlay_manager)
{
if (!in_begin_end && async_flip_requested.test_and_reset(flip_request::native_ui))
if (!in_begin_end && async_flip_requested & flip_request::native_ui)
{
flip((s32)current_display_buffer);
s32 buffer_id = (async_flip_requested & flip_request::emu_requested) ? async_flip_buffer : (s32)current_display_buffer;
flip(buffer_id);
}
}
}

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "overlays.h"
#include "../GSRender.h"
@ -35,7 +35,7 @@ namespace rsx
const auto now = get_system_time() - 1000000;
if ((now - rsxthr->last_flip_time) > min_refresh_duration_us)
{
rsxthr->async_flip_requested.test_and_set(rsx::thread::flip_request::native_ui);
rsxthr->async_flip_requested |= rsx::thread::flip_request::native_ui;
}
}
}

View File

@ -1356,10 +1356,9 @@ namespace rsx
void thread::do_local_task(FIFO_state state)
{
if (test(async_flip_requested, flip_request::emu_requested))
if (async_flip_requested & flip_request::any)
{
handle_emu_flip(async_flip_buffer);
async_flip_requested.test_and_reset(flip_request::emu_requested);
}
if (!in_begin_end && state != FIFO_state::lock_wait)
@ -2554,6 +2553,8 @@ namespace rsx
void thread::flip(int buffer)
{
async_flip_requested.clear();
if (g_cfg.video.frame_skip_enabled)
{
m_skip_frame_ctr++;
@ -2811,22 +2812,19 @@ namespace rsx
// requested through command buffer
if (is_rsxthr)
{
// async flip hasnt been handled before next requested...?
if (test(async_flip_requested, flip_request::emu_requested))
{
handle_emu_flip(async_flip_buffer);
async_flip_requested.test_and_reset(flip_request::emu_requested);
}
// NOTE: The flip will clear any queued flip requests
handle_emu_flip(buffer);
}
else // requested 'manually' through ppu syscall
{
// ignore multiple requests until previous happens
if (test(async_flip_requested, flip_request::emu_requested))
if (async_flip_requested & flip_request::emu_requested)
{
// ignore multiple requests until previous happens
return;
}
async_flip_buffer = buffer;
async_flip_requested.test_and_set(flip_request::emu_requested);
async_flip_requested |= flip_request::emu_requested;
}
}
@ -2914,10 +2912,6 @@ namespace rsx
int_flip_index++;
current_display_buffer = buffer;
flip(buffer);
// After each flip PS3 system is executing a routine that changes registers value to some default.
// Some game use this default state (SH3).
if (isHLE)
reset();
last_flip_time = get_system_time() - 1000000;
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
@ -2933,7 +2927,8 @@ namespace rsx
intr_thread->notify();
}
sys_rsx_flip_event(buffer);
sys_rsx_context_attribute(0x55555555, 0xFEC, buffer, 0, 0, 0);
}

View File

@ -323,6 +323,7 @@ namespace rsx
u64 timestamp_subvalue = 0;
protected:
std::thread::id m_rsx_thread;
atomic_t<bool> m_rsx_thread_exiting{true};
s32 m_return_addr{-1}, restore_ret_addr{-1};
std::array<push_buffer_vertex_info, 16> vertex_push_buffers;
@ -370,13 +371,13 @@ namespace rsx
enum class flip_request : u32
{
emu_requested,
native_ui,
emu_requested = 1,
native_ui = 2,
__bitset_enum_max
any = emu_requested | native_ui
};
atomic_t<bs_t<flip_request>> async_flip_requested{};
atomic_bitmask_t<flip_request> async_flip_requested{};
u8 async_flip_buffer{ 0 };
GcmTileInfo tiles[limits::tiles_count];

View File

@ -2192,10 +2192,12 @@ void VKGSRender::do_local_task(rsx::FIFO_state state)
if (m_overlay_manager)
{
if (!in_begin_end && async_flip_requested.test_and_reset(flip_request::native_ui))
if (!in_begin_end && async_flip_requested & flip_request::native_ui)
{
s32 buffer_id = (async_flip_requested & flip_request::emu_requested) ? async_flip_buffer : (s32)current_display_buffer;
flush_command_queue(true);
flip((s32)current_display_buffer);
flip((s32)buffer_id);
}
}
}

View File

@ -1116,6 +1116,8 @@ namespace rsx
void flip_command(thread* rsx, u32, u32 arg)
{
verify(HERE), rsx->isHLE;
rsx->reset();
rsx->request_emu_flip(arg);
}

View File

@ -784,4 +784,56 @@ namespace rsx
}
}
}
}
template <typename T, typename bitmask_type = u32>
class atomic_bitmask_t
{
private:
atomic_t<bitmask_type> m_data;
public:
atomic_bitmask_t() { m_data.store(0); };
~atomic_bitmask_t() {}
T load() const
{
return static_cast<T>(m_data.load());
}
void store(T value)
{
m_data.store(static_cast<bitmask_type>(value));
}
bool operator & (T mask) const
{
return ((m_data.load() & static_cast<bitmask_type>(mask)) != 0);
}
T operator | (T mask) const
{
return static_cast<T>(m_data.load() | static_cast<bitmask_type>(mask));
}
void operator &= (T mask)
{
m_data.fetch_and(static_cast<bitmask_type>(mask));
}
void operator |= (T mask)
{
m_data.fetch_or(static_cast<bitmask_type>(mask));
}
auto clear(T mask)
{
bitmask_type clear_mask = ~(static_cast<bitmask_type>(mask));
return m_data.and_fetch(clear_mask);
}
void clear()
{
m_data.store(0);
}
};
}