mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
semaphore_t, RSX fixes
1) GS_LOCK_WAIT_FLUSH semaphore eliminated 2) GS_LOCK_WAIT_FLIP semaphore left unused 3) cellRescSetWaitFlip/cellGcmSetWaitFlip purged: they don't wait for flip, it's a nonsense, they only generate some RSX command 4) Semaphores rewritten
This commit is contained in:
parent
71a378a3fb
commit
8e1991c1e1
@ -1,85 +0,0 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#include "Utilities/SSemaphore.h"
|
|
||||||
#include "Emu/System.h"
|
|
||||||
|
|
||||||
void SSemaphore::wait()
|
|
||||||
{
|
|
||||||
u32 order;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
if (m_count && m_out_order == m_in_order)
|
|
||||||
{
|
|
||||||
m_count--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
order = m_in_order++;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
CHECK_EMU_STATUS;
|
|
||||||
|
|
||||||
m_cond.wait_for(cv_lock, std::chrono::milliseconds(1));
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
if (m_count)
|
|
||||||
{
|
|
||||||
if (m_out_order == order)
|
|
||||||
{
|
|
||||||
m_count--;
|
|
||||||
m_out_order++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_cond.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SSemaphore::try_wait()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
|
|
||||||
if (m_count && m_in_order == m_out_order)
|
|
||||||
{
|
|
||||||
m_count--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SSemaphore::post()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
|
|
||||||
if (m_count < m_max)
|
|
||||||
{
|
|
||||||
m_count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cond.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SSemaphore::post_and_wait()
|
|
||||||
{
|
|
||||||
// TODO: merge these functions? Probably has a race condition.
|
|
||||||
if (try_wait()) return false;
|
|
||||||
|
|
||||||
post();
|
|
||||||
wait();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class SSemaphore
|
|
||||||
{
|
|
||||||
const u32 m_max;
|
|
||||||
u32 m_count;
|
|
||||||
u32 m_in_order;
|
|
||||||
u32 m_out_order;
|
|
||||||
std::mutex m_cv_mutex;
|
|
||||||
std::mutex m_mutex;
|
|
||||||
std::condition_variable m_cond;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SSemaphore(u32 value, u32 max = 1)
|
|
||||||
: m_max(max > 0 ? max : 0xffffffff)
|
|
||||||
, m_count(value > m_max ? m_max : value)
|
|
||||||
, m_in_order(0)
|
|
||||||
, m_out_order(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SSemaphore()
|
|
||||||
: m_max(0xffffffff)
|
|
||||||
, m_count(0)
|
|
||||||
, m_in_order(0)
|
|
||||||
, m_out_order(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~SSemaphore()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void wait();
|
|
||||||
|
|
||||||
bool try_wait();
|
|
||||||
|
|
||||||
void post();
|
|
||||||
|
|
||||||
bool post_and_wait();
|
|
||||||
};
|
|
120
Utilities/Semaphore.cpp
Normal file
120
Utilities/Semaphore.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Utilities/Semaphore.h"
|
||||||
|
|
||||||
|
bool semaphore_t::try_wait()
|
||||||
|
{
|
||||||
|
// check m_value without interlocked op
|
||||||
|
if (m_var.load().value == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to decrement m_value atomically
|
||||||
|
const auto old = m_var.atomic_op([](sync_var_t& var)
|
||||||
|
{
|
||||||
|
if (var.value)
|
||||||
|
{
|
||||||
|
var.value--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// recheck atomic result
|
||||||
|
if (old.value == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool semaphore_t::try_post()
|
||||||
|
{
|
||||||
|
// check m_value without interlocked op
|
||||||
|
if (m_var.load().value >= max_value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to increment m_value atomically
|
||||||
|
const auto old = m_var.atomic_op([&](sync_var_t& var)
|
||||||
|
{
|
||||||
|
if (var.value < max_value)
|
||||||
|
{
|
||||||
|
var.value++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// recheck atomic result
|
||||||
|
if (old.value >= max_value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old.waiters)
|
||||||
|
{
|
||||||
|
// notify waiting thread
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
m_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void semaphore_t::wait()
|
||||||
|
{
|
||||||
|
if (m_var.atomic_op([](sync_var_t& var) -> bool
|
||||||
|
{
|
||||||
|
if (var.value)
|
||||||
|
{
|
||||||
|
var.value--;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//var.waiters++;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
m_var.atomic_op([](sync_var_t& var)
|
||||||
|
{
|
||||||
|
var.waiters++;
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!m_var.atomic_op([](sync_var_t& var) -> bool
|
||||||
|
{
|
||||||
|
if (var.value)
|
||||||
|
{
|
||||||
|
var.value--;
|
||||||
|
var.waiters--;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
m_cv.wait(lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool semaphore_t::post_and_wait()
|
||||||
|
{
|
||||||
|
// TODO: merge these functions? Probably has a race condition.
|
||||||
|
if (try_wait()) return false;
|
||||||
|
|
||||||
|
try_post();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
37
Utilities/Semaphore.h
Normal file
37
Utilities/Semaphore.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class semaphore_t
|
||||||
|
{
|
||||||
|
// semaphore mutex
|
||||||
|
std::mutex m_mutex;
|
||||||
|
|
||||||
|
// semaphore condition variable
|
||||||
|
std::condition_variable m_cv;
|
||||||
|
|
||||||
|
struct sync_var_t
|
||||||
|
{
|
||||||
|
u32 value; // current semaphore value
|
||||||
|
u32 waiters; // current amount of waiters
|
||||||
|
};
|
||||||
|
|
||||||
|
// current semaphore value
|
||||||
|
atomic_t<sync_var_t> m_var;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// max semaphore value
|
||||||
|
const u32 max_value;
|
||||||
|
|
||||||
|
semaphore_t(u32 max_value = 1, u32 value = 0)
|
||||||
|
: m_var({ value, 0 })
|
||||||
|
, max_value(max_value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_wait();
|
||||||
|
|
||||||
|
bool try_post();
|
||||||
|
|
||||||
|
void wait();
|
||||||
|
|
||||||
|
bool post_and_wait();
|
||||||
|
};
|
@ -224,9 +224,9 @@ typedef s32(CellGcmContextCallback)(vm::ptr<CellGcmContextData>, u32);
|
|||||||
|
|
||||||
struct CellGcmContextData
|
struct CellGcmContextData
|
||||||
{
|
{
|
||||||
be_t<u32> begin;
|
vm::bptr<u32> begin;
|
||||||
be_t<u32> end;
|
vm::bptr<u32> end;
|
||||||
be_t<u32> current;
|
vm::bptr<u32> current;
|
||||||
vm::bptr<CellGcmContextCallback> callback;
|
vm::bptr<CellGcmContextCallback> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ GSLock::GSLock(GSRender& renderer, GSLockType type)
|
|||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.lock(); break;
|
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.lock(); break;
|
||||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.wait(); break;
|
|
||||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break;
|
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,8 +21,7 @@ GSLock::~GSLock()
|
|||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.unlock(); break;
|
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.unlock(); break;
|
||||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.post(); break;
|
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.try_post(); break;
|
||||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.post(); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ struct GSRender : public RSXThread
|
|||||||
enum GSLockType
|
enum GSLockType
|
||||||
{
|
{
|
||||||
GS_LOCK_NOT_WAIT,
|
GS_LOCK_NOT_WAIT,
|
||||||
GS_LOCK_WAIT_FLUSH,
|
|
||||||
GS_LOCK_WAIT_FLIP,
|
GS_LOCK_WAIT_FLIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,6 +258,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_sem_flip.post_and_wait();
|
||||||
|
|
||||||
auto sync = [&]()
|
auto sync = [&]()
|
||||||
{
|
{
|
||||||
double limit;
|
double limit;
|
||||||
@ -2499,14 +2501,6 @@ void RSXThread::Task()
|
|||||||
|
|
||||||
if (put == get || !Emu.IsRunning())
|
if (put == get || !Emu.IsRunning())
|
||||||
{
|
{
|
||||||
if (put == get)
|
|
||||||
{
|
|
||||||
if (m_flip_status == 0)
|
|
||||||
m_sem_flip.post_and_wait();
|
|
||||||
|
|
||||||
m_sem_flush.post_and_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "RSXFragmentProgram.h"
|
#include "RSXFragmentProgram.h"
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include "Utilities/SSemaphore.h"
|
#include "Utilities/Semaphore.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
#include "Utilities/Timer.h"
|
#include "Utilities/Timer.h"
|
||||||
|
|
||||||
@ -155,8 +155,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
std::mutex m_cs_main;
|
std::mutex m_cs_main;
|
||||||
SSemaphore m_sem_flush;
|
semaphore_t m_sem_flip;
|
||||||
SSemaphore m_sem_flip;
|
|
||||||
u64 m_last_flip_time;
|
u64 m_last_flip_time;
|
||||||
vm::ptr<void(u32)> m_flip_handler;
|
vm::ptr<void(u32)> m_flip_handler;
|
||||||
vm::ptr<void(u32)> m_user_handler;
|
vm::ptr<void(u32)> m_user_handler;
|
||||||
|
@ -320,9 +320,9 @@ void _cellGcmFunc15(vm::ptr<CellGcmContextData> context)
|
|||||||
u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount;
|
u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount;
|
||||||
|
|
||||||
// Called by cellGcmInit
|
// Called by cellGcmInit
|
||||||
s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> context, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||||
{
|
{
|
||||||
cellGcmSys.Warning("_cellGcmInitBody(context=*0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
|
cellGcmSys.Warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
|
||||||
|
|
||||||
if(!local_size && !local_addr)
|
if(!local_size && !local_addr)
|
||||||
{
|
{
|
||||||
@ -365,8 +365,8 @@ s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> context, u32 cmdSize, u32 ioSiz
|
|||||||
g_defaultCommandBufferBegin = ioAddress;
|
g_defaultCommandBufferBegin = ioAddress;
|
||||||
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
|
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
|
||||||
|
|
||||||
current_context.begin = g_defaultCommandBufferBegin + 4096; // 4 kb reserved at the beginning
|
current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning
|
||||||
current_context.end = g_defaultCommandBufferBegin + 32 * 1024 - 4; // 4b at the end for jump
|
current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump
|
||||||
current_context.current = current_context.begin;
|
current_context.current = current_context.begin;
|
||||||
current_context.callback.set(Emu.GetRSXCallback() - 4);
|
current_context.callback.set(Emu.GetRSXCallback() - 4);
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> context, u32 cmdSize, u32 ioSiz
|
|||||||
gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ???
|
gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ???
|
||||||
|
|
||||||
vm::get_ref<CellGcmContextData>(gcm_info.context_addr) = current_context;
|
vm::get_ref<CellGcmContextData>(gcm_info.context_addr) = current_context;
|
||||||
vm::write32(context.addr(), gcm_info.context_addr);
|
context->set(gcm_info.context_addr);
|
||||||
|
|
||||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||||
ctrl.put.store(0);
|
ctrl.put.store(0);
|
||||||
@ -480,59 +480,46 @@ void cellGcmSetFlipStatus()
|
|||||||
Emu.GetGSManager().GetRender().m_flip_status = 0;
|
Emu.GetGSManager().GetRender().m_flip_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellGcmSetPrepareFlip(PPUThread& CPU, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmSetPrepareFlip(ctx=0x%x, id=0x%x)", ctxt.addr(), id);
|
cellGcmSys.Log("cellGcmSetPrepareFlip(ctx=*0x%x, id=0x%x)", ctxt, id);
|
||||||
|
|
||||||
if(id > 7)
|
if (id > 7)
|
||||||
{
|
{
|
||||||
cellGcmSys.Error("cellGcmSetPrepareFlip : CELL_GCM_ERROR_FAILURE");
|
cellGcmSys.Error("cellGcmSetPrepareFlip : CELL_GCM_ERROR_FAILURE");
|
||||||
return CELL_GCM_ERROR_FAILURE;
|
return CELL_GCM_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
|
if (ctxt->current + 2 >= ctxt->end)
|
||||||
|
|
||||||
u32 current = ctxt->current;
|
|
||||||
|
|
||||||
if (current + 8 == ctxt->begin)
|
|
||||||
{
|
{
|
||||||
cellGcmSys.Error("cellGcmSetPrepareFlip : queue is full");
|
if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */))
|
||||||
return CELL_GCM_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current + 8 >= ctxt->end)
|
|
||||||
{
|
|
||||||
cellGcmSys.Error("Bad flip!");
|
|
||||||
if (s32 res = ctxt->callback(CPU, ctxt, 8 /* ??? */))
|
|
||||||
{
|
{
|
||||||
cellGcmSys.Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res);
|
cellGcmSys.Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current = ctxt->current;
|
*ctxt->current++ = 0x3fead | (1 << 18);
|
||||||
vm::write32(current, 0x3fead | (1 << 18));
|
*ctxt->current++ = id;
|
||||||
vm::write32(current + 4, id);
|
|
||||||
ctxt->current += 8;
|
|
||||||
|
|
||||||
if(ctxt.addr() == gcm_info.context_addr)
|
if (ctxt.addr() == gcm_info.context_addr)
|
||||||
{
|
{
|
||||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
vm::get_ref<CellGcmControl>(gcm_info.control_addr).put += 8;
|
||||||
ctrl.put.atomic_op([](be_t<u32>& value)
|
|
||||||
{
|
|
||||||
value += 8;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellGcmSetFlip(PPUThread& CPU, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
s32 cellGcmSetFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmSetFlip(ctx=0x%x, id=0x%x)", ctxt.addr(), id);
|
cellGcmSys.Log("cellGcmSetFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
|
||||||
|
|
||||||
s32 res = cellGcmSetPrepareFlip(CPU, ctxt, id);
|
if (s32 res = cellGcmSetPrepareFlip(ppu, ctxt, id))
|
||||||
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
|
{
|
||||||
|
if (res < 0) return CELL_GCM_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellGcmSetSecondVFrequency(u32 freq)
|
s32 cellGcmSetSecondVFrequency(u32 freq)
|
||||||
@ -610,9 +597,10 @@ void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler)
|
|||||||
|
|
||||||
s32 cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
|
s32 cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmSetWaitFlip(ctx=*0x%x)", ctxt);
|
cellGcmSys.Warning("cellGcmSetWaitFlip(ctx=*0x%x)", ctxt);
|
||||||
|
|
||||||
|
// TODO: emit RSX command for "wait flip" operation
|
||||||
|
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLIP);
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,18 +1089,18 @@ void cellGcmSetDefaultCommandBuffer()
|
|||||||
// Other
|
// Other
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
s32 _cellGcmSetFlipCommand(PPUThread& CPU, vm::ptr<CellGcmContextData> ctx, u32 id)
|
s32 _cellGcmSetFlipCommand(PPUThread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmSetFlipCommand(ctx=*0x%x, id=0x%x)", ctx, id);
|
cellGcmSys.Log("cellGcmSetFlipCommand(ctx=*0x%x, id=0x%x)", ctx, id);
|
||||||
|
|
||||||
return cellGcmSetPrepareFlip(CPU, ctx, id);
|
return cellGcmSetPrepareFlip(ppu, ctx, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 _cellGcmSetFlipCommandWithWaitLabel(PPUThread& CPU, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
|
s32 _cellGcmSetFlipCommandWithWaitLabel(PPUThread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
|
cellGcmSys.Log("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
|
||||||
|
|
||||||
s32 res = cellGcmSetPrepareFlip(CPU, ctx, id);
|
s32 res = cellGcmSetPrepareFlip(ppu, ctx, id);
|
||||||
vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value);
|
vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value);
|
||||||
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
|
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
|
||||||
}
|
}
|
||||||
@ -1200,9 +1188,7 @@ static bool isInCommandBufferExcept(u32 getPos, u32 bufferBegin, u32 bufferEnd)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This function was originally located in lv2/SC_GCM and appears in RPCS3 as a lv2 syscall with id 1023,
|
// TODO: Avoid using syscall 1023 for calling this function
|
||||||
// which according to lv2 dumps isn't the case. So, is this a proper place for this function?
|
|
||||||
|
|
||||||
s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
||||||
{
|
{
|
||||||
cellGcmSys.Log("cellGcmCallback(context=*0x%x, count=0x%x)", context, count);
|
cellGcmSys.Log("cellGcmCallback(context=*0x%x, count=0x%x)", context, count);
|
||||||
@ -1210,16 +1196,16 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
|||||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||||
const std::chrono::time_point<std::chrono::system_clock> enterWait = std::chrono::system_clock::now();
|
const std::chrono::time_point<std::chrono::system_clock> enterWait = std::chrono::system_clock::now();
|
||||||
// Flush command buffer (ie allow RSX to read up to context->current)
|
// Flush command buffer (ie allow RSX to read up to context->current)
|
||||||
ctrl.put.exchange(getOffsetFromAddress(context->current));
|
ctrl.put.exchange(getOffsetFromAddress(context->current.addr()));
|
||||||
|
|
||||||
std::pair<u32, u32> newCommandBuffer = getNextCommandBufferBeginEnd(context->current);
|
std::pair<u32, u32> newCommandBuffer = getNextCommandBufferBeginEnd(context->current.addr());
|
||||||
u32 offset = getOffsetFromAddress(newCommandBuffer.first);
|
u32 offset = getOffsetFromAddress(newCommandBuffer.first);
|
||||||
// Write jump instruction
|
// Write jump instruction
|
||||||
vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset);
|
*context->current = CELL_GCM_METHOD_FLAG_JUMP | offset;
|
||||||
// Update current command buffer
|
// Update current command buffer
|
||||||
context->begin = newCommandBuffer.first;
|
context->begin.set(newCommandBuffer.first);
|
||||||
context->current = newCommandBuffer.first;
|
context->current.set(newCommandBuffer.first);
|
||||||
context->end = newCommandBuffer.second;
|
context->end.set(newCommandBuffer.second);
|
||||||
|
|
||||||
// Wait for rsx to "release" the new command buffer
|
// Wait for rsx to "release" the new command buffer
|
||||||
while (!Emu.IsStopped())
|
while (!Emu.IsStopped())
|
||||||
@ -1235,55 +1221,6 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
||||||
//if (0)
|
|
||||||
//{
|
|
||||||
// auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
|
||||||
// be_t<u32> res = context->current - context->begin - ctrl.put.load();
|
|
||||||
|
|
||||||
// if (res != 0)
|
|
||||||
// {
|
|
||||||
// GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// memmove(vm::get_ptr<void>(context->begin), vm::get_ptr<void>(context->current - res), res);
|
|
||||||
|
|
||||||
// context->current = context->begin + res;
|
|
||||||
// ctrl.put.store(res);
|
|
||||||
// ctrl.get.store(0);
|
|
||||||
|
|
||||||
// return CELL_OK;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
|
||||||
|
|
||||||
// preparations for changing the place (for optimized FIFO mode)
|
|
||||||
//auto cmd = vm::ptr<u32>::make(context->current);
|
|
||||||
//cmd[0] = 0x41D6C;
|
|
||||||
//cmd[1] = 0x20;
|
|
||||||
//cmd[2] = 0x41D74;
|
|
||||||
//cmd[3] = 0; // some incrementing by module value
|
|
||||||
//context->current += 0x10;
|
|
||||||
|
|
||||||
//if (0)
|
|
||||||
//{
|
|
||||||
// const u32 address = context->begin;
|
|
||||||
// const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
|
|
||||||
// assert(upper != 0xFFFF);
|
|
||||||
// const u32 offset = (upper << 20) | (address & 0xFFFFF);
|
|
||||||
// vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset); // set JUMP cmd
|
|
||||||
|
|
||||||
// auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
|
||||||
// ctrl.put.exchange(offset);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0));
|
|
||||||
//}
|
|
||||||
|
|
||||||
//context->current = context->begin; // rewind to the beginning
|
|
||||||
// TODO: something is missing
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -17,7 +17,7 @@ extern void cellGcmSetFlipHandler(vm::ptr<void(u32)> handler);
|
|||||||
extern void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler);
|
extern void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler);
|
||||||
extern s32 cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset);
|
extern s32 cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset);
|
||||||
extern s32 cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
|
extern s32 cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
|
||||||
extern s32 cellGcmSetPrepareFlip(PPUThread& CPU, vm::ptr<CellGcmContextData> ctx, u32 id);
|
extern s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id);
|
||||||
extern s32 cellGcmSetSecondVFrequency(u32 freq);
|
extern s32 cellGcmSetSecondVFrequency(u32 freq);
|
||||||
extern u32 cellGcmGetLabelAddress(u8 index);
|
extern u32 cellGcmGetLabelAddress(u8 index);
|
||||||
extern u32 cellGcmGetTiledPitchSize(u32 size);
|
extern u32 cellGcmGetTiledPitchSize(u32 size);
|
||||||
@ -467,7 +467,6 @@ void InitMembers()
|
|||||||
void SetupRsxRenderingStates(vm::ptr<CellGcmContextData>& cntxt)
|
void SetupRsxRenderingStates(vm::ptr<CellGcmContextData>& cntxt)
|
||||||
{
|
{
|
||||||
//TODO: use cntxt
|
//TODO: use cntxt
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLUSH);
|
|
||||||
GSRender& r = Emu.GetGSManager().GetRender();
|
GSRender& r = Emu.GetGSManager().GetRender();
|
||||||
r.m_set_color_mask = true; r.m_color_mask_a = r.m_color_mask_r = r.m_color_mask_g = r.m_color_mask_b = true;
|
r.m_set_color_mask = true; r.m_color_mask_a = r.m_color_mask_r = r.m_color_mask_g = r.m_color_mask_b = true;
|
||||||
r.m_set_depth_mask = true; r.m_depth_mask = 0;
|
r.m_set_depth_mask = true; r.m_depth_mask = 0;
|
||||||
@ -514,7 +513,6 @@ void SetupRsxRenderingStates(vm::ptr<CellGcmContextData>& cntxt)
|
|||||||
|
|
||||||
void SetupVertexArrays(vm::ptr<CellGcmContextData>& cntxt)
|
void SetupVertexArrays(vm::ptr<CellGcmContextData>& cntxt)
|
||||||
{
|
{
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLUSH);
|
|
||||||
GSRender& r = Emu.GetGSManager().GetRender();
|
GSRender& r = Emu.GetGSManager().GetRender();
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
@ -538,7 +536,6 @@ void SetupSurfaces(vm::ptr<CellGcmContextData>& cntxt)
|
|||||||
dstOffset1 = s_rescInternalInstance->m_dstOffsets[s_rescInternalInstance->m_bufIdPalMidNow];
|
dstOffset1 = s_rescInternalInstance->m_dstOffsets[s_rescInternalInstance->m_bufIdPalMidNow];
|
||||||
}
|
}
|
||||||
|
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLUSH);
|
|
||||||
GSRender& r = Emu.GetGSManager().GetRender();
|
GSRender& r = Emu.GetGSManager().GetRender();
|
||||||
|
|
||||||
r.m_surface_type = CELL_GCM_SURFACE_PITCH;
|
r.m_surface_type = CELL_GCM_SURFACE_PITCH;
|
||||||
@ -1023,8 +1020,9 @@ s32 cellRescSetConvertAndFlip(PPUThread& CPU, vm::ptr<CellGcmContextData> cntxt,
|
|||||||
|
|
||||||
s32 cellRescSetWaitFlip()
|
s32 cellRescSetWaitFlip()
|
||||||
{
|
{
|
||||||
cellResc.Log("cellRescSetWaitFlip()");
|
cellResc.Warning("cellRescSetWaitFlip()");
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLIP);
|
|
||||||
|
// TODO: emit RSX command for "wait flip" operation
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<ClCompile Include="..\Utilities\rPlatform.cpp" />
|
<ClCompile Include="..\Utilities\rPlatform.cpp" />
|
||||||
<ClCompile Include="..\Utilities\rTime.cpp" />
|
<ClCompile Include="..\Utilities\rTime.cpp" />
|
||||||
<ClCompile Include="..\Utilities\rXml.cpp" />
|
<ClCompile Include="..\Utilities\rXml.cpp" />
|
||||||
<ClCompile Include="..\Utilities\SSemaphore.cpp" />
|
<ClCompile Include="..\Utilities\Semaphore.cpp" />
|
||||||
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
||||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\PPUInterpreter.cpp" />
|
<ClCompile Include="Emu\Cell\PPUInterpreter.cpp" />
|
||||||
@ -318,9 +318,9 @@
|
|||||||
<ClInclude Include="..\Utilities\rPlatform.h" />
|
<ClInclude Include="..\Utilities\rPlatform.h" />
|
||||||
<ClInclude Include="..\Utilities\rTime.h" />
|
<ClInclude Include="..\Utilities\rTime.h" />
|
||||||
<ClInclude Include="..\Utilities\rXml.h" />
|
<ClInclude Include="..\Utilities\rXml.h" />
|
||||||
|
<ClInclude Include="..\Utilities\Semaphore.h" />
|
||||||
<ClInclude Include="..\Utilities\simpleini\ConvertUTF.h" />
|
<ClInclude Include="..\Utilities\simpleini\ConvertUTF.h" />
|
||||||
<ClInclude Include="..\Utilities\simpleini\SimpleIni.h" />
|
<ClInclude Include="..\Utilities\simpleini\SimpleIni.h" />
|
||||||
<ClInclude Include="..\Utilities\SSemaphore.h" />
|
|
||||||
<ClInclude Include="..\Utilities\StrFmt.h" />
|
<ClInclude Include="..\Utilities\StrFmt.h" />
|
||||||
<ClInclude Include="..\Utilities\Thread.h" />
|
<ClInclude Include="..\Utilities\Thread.h" />
|
||||||
<ClInclude Include="..\Utilities\Timer.h" />
|
<ClInclude Include="..\Utilities\Timer.h" />
|
||||||
|
@ -476,9 +476,6 @@
|
|||||||
<ClCompile Include="Emu\SysCalls\Modules\sys_http.cpp">
|
<ClCompile Include="Emu\SysCalls\Modules\sys_http.cpp">
|
||||||
<Filter>Emu\SysCalls\currently_unused</Filter>
|
<Filter>Emu\SysCalls\currently_unused</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\Utilities\SSemaphore.cpp">
|
|
||||||
<Filter>Utilities</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\sys_process.cpp">
|
<ClCompile Include="Emu\SysCalls\lv2\sys_process.cpp">
|
||||||
<Filter>Emu\SysCalls\lv2</Filter>
|
<Filter>Emu\SysCalls\lv2</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -884,6 +881,9 @@
|
|||||||
<ClCompile Include="Emu\SysCalls\Modules\sceNpUtil.cpp">
|
<ClCompile Include="Emu\SysCalls\Modules\sceNpUtil.cpp">
|
||||||
<Filter>Emu\SysCalls\Modules</Filter>
|
<Filter>Emu\SysCalls\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Utilities\Semaphore.cpp">
|
||||||
|
<Filter>Utilities</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
@ -1267,9 +1267,6 @@
|
|||||||
<ClInclude Include="Emu\Event.h">
|
<ClInclude Include="Emu\Event.h">
|
||||||
<Filter>Emu\SysCalls</Filter>
|
<Filter>Emu\SysCalls</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\Utilities\SSemaphore.h">
|
|
||||||
<Filter>Utilities</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Emu\SysCalls\lv2\sys_process.h">
|
<ClInclude Include="Emu\SysCalls\lv2\sys_process.h">
|
||||||
<Filter>Emu\SysCalls\lv2</Filter>
|
<Filter>Emu\SysCalls\lv2</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -1738,5 +1735,8 @@
|
|||||||
<ClInclude Include="Emu\SysCalls\Modules\sceNpUtil.h">
|
<ClInclude Include="Emu\SysCalls\Modules\sceNpUtil.h">
|
||||||
<Filter>Emu\SysCalls\Modules</Filter>
|
<Filter>Emu\SysCalls\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\Utilities\Semaphore.h">
|
||||||
|
<Filter>Utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user