mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-29 09:32:42 +00:00
rsx: Cleanup changes for the flip patch
This commit is contained in:
parent
699eadc84f
commit
a3d44b5e1f
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user