2013-12-19 17:10:14 +00:00
|
|
|
#include "ta_ctx.h"
|
2020-12-25 11:08:44 +00:00
|
|
|
#include "spg.h"
|
2019-09-11 13:09:23 +00:00
|
|
|
#include "oslib/oslib.h"
|
2021-03-01 09:13:40 +00:00
|
|
|
#include "cfg/option.h"
|
2015-08-11 21:55:48 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
extern u32 fskip;
|
|
|
|
extern u32 FrameCount;
|
2020-12-25 11:08:44 +00:00
|
|
|
static int RenderCount;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
TA_context* ta_ctx;
|
|
|
|
tad_context ta_tad;
|
|
|
|
|
|
|
|
TA_context* vd_ctx;
|
|
|
|
rend_context vd_rc;
|
|
|
|
|
2018-04-09 19:11:06 +00:00
|
|
|
// helper for 32 byte aligned memory allocation
|
|
|
|
void* OS_aligned_malloc(size_t align, size_t size)
|
|
|
|
{
|
2019-08-31 15:36:34 +00:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
return __mingw_aligned_malloc(size, align);
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
return _aligned_malloc(size, align);
|
|
|
|
#else
|
|
|
|
void *result;
|
|
|
|
if (posix_memalign(&result, align, size))
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return result;
|
|
|
|
#endif
|
2018-04-09 19:11:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// helper for 32 byte aligned memory de-allocation
|
|
|
|
void OS_aligned_free(void *ptr)
|
|
|
|
{
|
2019-08-31 15:36:34 +00:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
__mingw_aligned_free(ptr);
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
_aligned_free(ptr);
|
|
|
|
#else
|
|
|
|
free(ptr);
|
|
|
|
#endif
|
2018-04-09 19:11:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
void SetCurrentTARC(u32 addr)
|
|
|
|
{
|
|
|
|
if (addr != TACTX_NONE)
|
|
|
|
{
|
|
|
|
if (ta_ctx)
|
|
|
|
SetCurrentTARC(TACTX_NONE);
|
|
|
|
|
|
|
|
verify(ta_ctx == 0);
|
|
|
|
//set new context
|
|
|
|
ta_ctx = tactx_Find(addr,true);
|
|
|
|
|
|
|
|
//copy cached params
|
|
|
|
ta_tad = ta_ctx->tad;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Flush cache to context
|
|
|
|
verify(ta_ctx != 0);
|
|
|
|
ta_ctx->tad=ta_tad;
|
|
|
|
|
|
|
|
//clear context
|
|
|
|
ta_ctx=0;
|
2014-04-25 16:57:34 +00:00
|
|
|
ta_tad.Reset(0);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 12:24:33 +00:00
|
|
|
static std::mutex mtx_rqueue;
|
2013-12-19 17:10:14 +00:00
|
|
|
TA_context* rqueue;
|
2019-04-27 12:08:43 +00:00
|
|
|
cResetEvent frame_finished;
|
2015-08-11 21:55:48 +00:00
|
|
|
|
2014-05-02 00:43:34 +00:00
|
|
|
bool QueueRender(TA_context* ctx)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
verify(ctx != 0);
|
|
|
|
|
2020-12-25 11:08:44 +00:00
|
|
|
bool skipFrame = false;
|
|
|
|
RenderCount++;
|
2021-03-01 09:13:40 +00:00
|
|
|
if (RenderCount % (config::SkipFrame + 1) != 0)
|
2020-12-25 11:08:44 +00:00
|
|
|
skipFrame = true;
|
2021-03-01 09:13:40 +00:00
|
|
|
else if (rqueue && (config::AutoSkipFrame == 0
|
|
|
|
|| (config::AutoSkipFrame == 1 && SH4FastEnough)))
|
2020-12-25 11:08:44 +00:00
|
|
|
// The previous render hasn't completed yet so we wait.
|
|
|
|
// If autoskipframe is enabled (normal level), we only do so if the CPU is running
|
|
|
|
// fast enough over the last frames
|
2015-08-11 21:55:48 +00:00
|
|
|
frame_finished.Wait();
|
|
|
|
|
2020-12-25 11:08:44 +00:00
|
|
|
if (skipFrame || rqueue)
|
2019-08-19 15:19:27 +00:00
|
|
|
{
|
2018-05-11 17:08:54 +00:00
|
|
|
tactx_Recycle(ctx);
|
|
|
|
fskip++;
|
|
|
|
return false;
|
2014-05-02 00:43:34 +00:00
|
|
|
}
|
|
|
|
|
2015-08-11 21:55:48 +00:00
|
|
|
frame_finished.Reset();
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.lock();
|
2013-12-19 17:10:14 +00:00
|
|
|
TA_context* old = rqueue;
|
|
|
|
rqueue=ctx;
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2014-05-02 00:43:34 +00:00
|
|
|
verify(!old);
|
|
|
|
|
|
|
|
return true;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TA_context* DequeueRender()
|
|
|
|
{
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.lock();
|
2013-12-19 17:10:14 +00:00
|
|
|
TA_context* rv = rqueue;
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
if (rv)
|
|
|
|
FrameCount++;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-07-28 21:43:03 +00:00
|
|
|
bool rend_framePending() {
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.lock();
|
2015-07-28 21:43:03 +00:00
|
|
|
TA_context* rv = rqueue;
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.unlock();
|
2015-07-28 21:43:03 +00:00
|
|
|
|
|
|
|
return rv != 0;
|
|
|
|
}
|
|
|
|
|
2014-05-02 00:43:34 +00:00
|
|
|
void FinishRender(TA_context* ctx)
|
|
|
|
{
|
2019-02-06 18:57:13 +00:00
|
|
|
if (ctx != NULL)
|
2019-06-21 12:10:04 +00:00
|
|
|
{
|
|
|
|
verify(rqueue == ctx);
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.lock();
|
2019-06-21 12:10:04 +00:00
|
|
|
rqueue = NULL;
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_rqueue.unlock();
|
2019-06-21 12:10:04 +00:00
|
|
|
|
2019-02-06 18:57:13 +00:00
|
|
|
tactx_Recycle(ctx);
|
2019-06-21 12:10:04 +00:00
|
|
|
}
|
2015-08-11 21:55:48 +00:00
|
|
|
frame_finished.Set();
|
2014-05-02 00:43:34 +00:00
|
|
|
}
|
|
|
|
|
2020-03-30 12:24:33 +00:00
|
|
|
static std::mutex mtx_pool;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
static std::vector<TA_context*> ctx_pool;
|
|
|
|
static std::vector<TA_context*> ctx_list;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
TA_context* tactx_Alloc()
|
|
|
|
{
|
|
|
|
TA_context* rv = 0;
|
|
|
|
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.lock();
|
2013-12-19 17:10:14 +00:00
|
|
|
if (ctx_pool.size())
|
|
|
|
{
|
|
|
|
rv = ctx_pool[ctx_pool.size()-1];
|
|
|
|
ctx_pool.pop_back();
|
|
|
|
}
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
if (!rv)
|
|
|
|
{
|
|
|
|
rv = new TA_context();
|
|
|
|
rv->Alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tactx_Recycle(TA_context* poped_ctx)
|
|
|
|
{
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.lock();
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
if (ctx_pool.size()>2)
|
|
|
|
{
|
|
|
|
poped_ctx->Free();
|
|
|
|
delete poped_ctx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
poped_ctx->Reset();
|
|
|
|
ctx_pool.push_back(poped_ctx);
|
|
|
|
}
|
|
|
|
}
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TA_context* tactx_Find(u32 addr, bool allocnew)
|
|
|
|
{
|
2013-12-25 17:47:51 +00:00
|
|
|
for (size_t i=0; i<ctx_list.size(); i++)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
if (ctx_list[i]->Address==addr)
|
|
|
|
return ctx_list[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allocnew)
|
|
|
|
{
|
|
|
|
TA_context* rv = tactx_Alloc();
|
|
|
|
rv->Address=addr;
|
|
|
|
ctx_list.push_back(rv);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
return 0;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TA_context* tactx_Pop(u32 addr)
|
|
|
|
{
|
2013-12-25 17:47:51 +00:00
|
|
|
for (size_t i=0; i<ctx_list.size(); i++)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
if (ctx_list[i]->Address==addr)
|
|
|
|
{
|
|
|
|
TA_context* rv = ctx_list[i];
|
|
|
|
|
|
|
|
if (ta_ctx == rv)
|
|
|
|
SetCurrentTARC(TACTX_NONE);
|
|
|
|
|
|
|
|
ctx_list.erase(ctx_list.begin() + i);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-10-29 19:02:12 +00:00
|
|
|
|
|
|
|
void tactx_Term()
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < ctx_list.size(); i++)
|
|
|
|
{
|
|
|
|
ctx_list[i]->Free();
|
|
|
|
delete ctx_list[i];
|
|
|
|
}
|
2019-02-25 16:52:53 +00:00
|
|
|
ctx_list.clear();
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.lock();
|
2018-10-29 19:02:12 +00:00
|
|
|
{
|
|
|
|
for (size_t i = 0; i < ctx_pool.size(); i++)
|
|
|
|
{
|
|
|
|
ctx_pool[i]->Free();
|
|
|
|
delete ctx_pool[i];
|
|
|
|
}
|
|
|
|
}
|
2019-02-25 16:52:53 +00:00
|
|
|
ctx_pool.clear();
|
2020-03-30 12:24:33 +00:00
|
|
|
mtx_pool.unlock();
|
2018-10-29 19:02:12 +00:00
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
|
|
|
|
const u32 NULL_CONTEXT = ~0u;
|
|
|
|
|
|
|
|
void SerializeTAContext(void **data, unsigned int *total_size)
|
|
|
|
{
|
|
|
|
if (ta_ctx == nullptr)
|
|
|
|
{
|
|
|
|
REICAST_S(NULL_CONTEXT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
REICAST_S(ta_ctx->Address);
|
|
|
|
const u32 taSize = ta_tad.thd_data - ta_tad.thd_root;
|
|
|
|
REICAST_S(taSize);
|
|
|
|
REICAST_SA(ta_tad.thd_root, taSize);
|
2020-12-15 14:09:42 +00:00
|
|
|
REICAST_S(ta_tad.render_pass_count);
|
|
|
|
for (u32 i = 0; i < ta_tad.render_pass_count; i++)
|
|
|
|
{
|
|
|
|
u32 offset = (u32)(ta_tad.render_passes[i] - ta_tad.thd_root);
|
|
|
|
REICAST_S(offset);
|
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
}
|
|
|
|
|
2020-12-15 15:27:34 +00:00
|
|
|
void UnserializeTAContext(void **data, unsigned int *total_size, serialize_version_enum version)
|
2020-07-06 14:28:09 +00:00
|
|
|
{
|
|
|
|
u32 address;
|
|
|
|
REICAST_US(address);
|
|
|
|
if (address == NULL_CONTEXT)
|
|
|
|
return;
|
|
|
|
SetCurrentTARC(address);
|
|
|
|
u32 size;
|
|
|
|
REICAST_US(size);
|
|
|
|
REICAST_USA(ta_tad.thd_root, size);
|
|
|
|
ta_tad.thd_data = ta_tad.thd_root + size;
|
2020-12-15 15:27:34 +00:00
|
|
|
if (version >= V12)
|
|
|
|
{
|
|
|
|
REICAST_US(ta_tad.render_pass_count);
|
|
|
|
for (u32 i = 0; i < ta_tad.render_pass_count; i++)
|
|
|
|
{
|
|
|
|
u32 offset;
|
|
|
|
REICAST_US(offset);
|
|
|
|
ta_tad.render_passes[i] = ta_tad.thd_root + offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2020-12-15 14:09:42 +00:00
|
|
|
{
|
2020-12-15 15:27:34 +00:00
|
|
|
ta_tad.render_pass_count = 0;
|
2020-12-15 14:09:42 +00:00
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
}
|