2013-12-19 17:10:14 +00:00
|
|
|
#include "ta_ctx.h"
|
2020-12-25 11:08:44 +00:00
|
|
|
#include "spg.h"
|
2021-03-01 09:13:40 +00:00
|
|
|
#include "cfg/option.h"
|
2021-09-03 09:11:46 +00:00
|
|
|
#include "Renderer_if.h"
|
2021-11-13 14:56:42 +00:00
|
|
|
#include "serialize.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;
|
|
|
|
|
2022-01-31 19:40:09 +00:00
|
|
|
static void tactx_Recycle(TA_context* ctx);
|
2022-01-29 17:39:38 +00:00
|
|
|
static TA_context *tactx_Find(u32 addr, bool allocnew = false);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2021-09-02 15:51:23 +00:00
|
|
|
bool skipFrame = settings.disableRenderer;
|
|
|
|
if (!skipFrame)
|
|
|
|
{
|
|
|
|
RenderCount++;
|
|
|
|
if (RenderCount % (config::SkipFrame + 1) != 0)
|
|
|
|
skipFrame = true;
|
|
|
|
else if (config::ThreadedRendering && rqueue != nullptr
|
|
|
|
&& (config::AutoSkipFrame == 0 || (config::AutoSkipFrame == 1 && SH4FastEnough)))
|
|
|
|
// 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
|
|
|
|
frame_finished.Wait();
|
|
|
|
}
|
2015-08-11 21:55:48 +00:00
|
|
|
|
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);
|
2021-09-02 15:51:23 +00:00
|
|
|
if (!settings.disableRenderer)
|
|
|
|
fskip++;
|
2018-05-11 17:08:54 +00:00
|
|
|
return false;
|
2014-05-02 00:43:34 +00:00
|
|
|
}
|
2021-09-03 09:11:46 +00:00
|
|
|
// disable net rollbacks until the render thread has processed the frame
|
|
|
|
rend_disable_rollback();
|
2021-05-02 13:14:26 +00:00
|
|
|
frame_finished.Reset();
|
2021-09-07 14:43:50 +00:00
|
|
|
verify(rqueue == nullptr);
|
|
|
|
rqueue = ctx;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2014-05-02 00:43:34 +00:00
|
|
|
|
|
|
|
return true;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TA_context* DequeueRender()
|
|
|
|
{
|
2021-09-07 14:43:50 +00:00
|
|
|
if (rqueue != nullptr)
|
2013-12-19 17:10:14 +00:00
|
|
|
FrameCount++;
|
|
|
|
|
2021-09-07 14:43:50 +00:00
|
|
|
return rqueue;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2015-07-28 21:43:03 +00:00
|
|
|
bool rend_framePending() {
|
2021-09-07 14:43:50 +00:00
|
|
|
return rqueue != nullptr;
|
2015-07-28 21:43:03 +00:00
|
|
|
}
|
|
|
|
|
2014-05-02 00:43:34 +00:00
|
|
|
void FinishRender(TA_context* ctx)
|
|
|
|
{
|
2021-09-07 14:43:50 +00:00
|
|
|
if (ctx != nullptr)
|
2019-06-21 12:10:04 +00:00
|
|
|
{
|
|
|
|
verify(rqueue == ctx);
|
2021-09-07 14:43:50 +00:00
|
|
|
rqueue = nullptr;
|
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
|
|
|
}
|
|
|
|
|
2022-05-15 11:37:58 +00:00
|
|
|
static std::mutex mtx_pool;
|
|
|
|
|
|
|
|
static std::vector<TA_context*> ctx_pool;
|
2020-03-29 17:29:14 +00:00
|
|
|
static std::vector<TA_context*> ctx_list;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2022-05-16 11:04:38 +00:00
|
|
|
TA_context *tactx_Alloc()
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2022-05-15 11:37:58 +00:00
|
|
|
TA_context *ctx = nullptr;
|
|
|
|
|
|
|
|
mtx_pool.lock();
|
|
|
|
if (!ctx_pool.empty())
|
|
|
|
{
|
|
|
|
ctx = ctx_pool.back();
|
|
|
|
ctx_pool.pop_back();
|
|
|
|
}
|
|
|
|
mtx_pool.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2022-05-15 11:37:58 +00:00
|
|
|
if (ctx == nullptr)
|
|
|
|
{
|
|
|
|
ctx = new TA_context();
|
|
|
|
ctx->Alloc();
|
|
|
|
}
|
2022-01-31 19:40:09 +00:00
|
|
|
return ctx;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 19:40:09 +00:00
|
|
|
static void tactx_Recycle(TA_context* ctx)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
if (ctx->nextContext != nullptr)
|
|
|
|
tactx_Recycle(ctx->nextContext);
|
2022-05-15 11:37:58 +00:00
|
|
|
mtx_pool.lock();
|
|
|
|
if (ctx_pool.size() > 3)
|
|
|
|
{
|
|
|
|
delete ctx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ctx->Reset();
|
|
|
|
ctx_pool.push_back(ctx);
|
|
|
|
}
|
|
|
|
mtx_pool.unlock();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 19:40:09 +00:00
|
|
|
static TA_context *tactx_Find(u32 addr, bool allocnew)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
for (TA_context *ctx : ctx_list)
|
|
|
|
if (ctx->Address == addr)
|
|
|
|
return ctx;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
if (allocnew)
|
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
TA_context *ctx = tactx_Alloc();
|
|
|
|
ctx->Address = addr;
|
|
|
|
ctx_list.push_back(ctx);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2022-01-31 19:40:09 +00:00
|
|
|
return ctx;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2022-01-31 19:40:09 +00:00
|
|
|
return nullptr;
|
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()
|
|
|
|
{
|
2021-03-05 17:20:09 +00:00
|
|
|
if (ta_ctx != nullptr)
|
|
|
|
SetCurrentTARC(TACTX_NONE);
|
|
|
|
|
2022-01-31 19:40:09 +00:00
|
|
|
for (TA_context *ctx : ctx_list)
|
|
|
|
delete ctx;
|
2019-02-25 16:52:53 +00:00
|
|
|
ctx_list.clear();
|
2022-05-15 11:37:58 +00:00
|
|
|
|
|
|
|
mtx_pool.lock();
|
|
|
|
for (TA_context *ctx : ctx_pool)
|
|
|
|
delete ctx;
|
|
|
|
ctx_pool.clear();
|
|
|
|
mtx_pool.unlock();
|
2018-10-29 19:02:12 +00:00
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
|
|
|
|
const u32 NULL_CONTEXT = ~0u;
|
|
|
|
|
2021-11-13 14:56:42 +00:00
|
|
|
static void serializeContext(Serializer& ser, const TA_context *ctx)
|
2020-07-06 14:28:09 +00:00
|
|
|
{
|
2021-11-13 14:56:42 +00:00
|
|
|
if (ser.dryrun())
|
2020-07-06 14:28:09 +00:00
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
// Maximum size: address, size, data
|
|
|
|
ser.skip(4 + 4 + TA_DATA_SIZE);
|
2020-07-06 14:28:09 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-11-13 14:56:42 +00:00
|
|
|
if (ctx == nullptr)
|
2021-07-11 15:42:30 +00:00
|
|
|
{
|
2021-11-13 14:56:42 +00:00
|
|
|
ser << NULL_CONTEXT;
|
2021-07-11 15:42:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-11-13 14:56:42 +00:00
|
|
|
ser << ctx->Address;
|
|
|
|
const tad_context& tad = ctx == ::ta_ctx ? ta_tad : ctx->tad;
|
|
|
|
const u32 taSize = tad.thd_data - tad.thd_root;
|
|
|
|
ser << taSize;
|
|
|
|
ser.serialize(tad.thd_root, taSize);
|
2020-07-06 14:28:09 +00:00
|
|
|
}
|
|
|
|
|
2021-11-13 14:56:42 +00:00
|
|
|
static void deserializeContext(Deserializer& deser, TA_context **pctx)
|
2020-07-06 14:28:09 +00:00
|
|
|
{
|
|
|
|
u32 address;
|
2021-11-13 14:56:42 +00:00
|
|
|
deser >> address;
|
2020-07-06 14:28:09 +00:00
|
|
|
if (address == NULL_CONTEXT)
|
2021-09-07 14:43:50 +00:00
|
|
|
{
|
|
|
|
*pctx = nullptr;
|
2020-07-06 14:28:09 +00:00
|
|
|
return;
|
2021-09-07 14:43:50 +00:00
|
|
|
}
|
|
|
|
*pctx = tactx_Find(address, true);
|
2020-07-06 14:28:09 +00:00
|
|
|
u32 size;
|
2021-11-13 14:56:42 +00:00
|
|
|
deser >> size;
|
2021-09-07 14:43:50 +00:00
|
|
|
tad_context& tad = (*pctx)->tad;
|
2021-11-13 14:56:42 +00:00
|
|
|
deser.deserialize(tad.thd_root, size);
|
2021-09-07 14:43:50 +00:00
|
|
|
tad.thd_data = tad.thd_root + size;
|
2022-01-31 19:40:09 +00:00
|
|
|
if ((deser.version() >= Deserializer::V12 && deser.version() < Deserializer::V26)
|
|
|
|
|| (deser.version() >= Deserializer::V12_LIBRETRO && deser.version() < Deserializer::V5))
|
2020-12-15 14:09:42 +00:00
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
u32 render_pass_count;
|
|
|
|
deser >> render_pass_count;
|
|
|
|
deser.skip(sizeof(u32) * render_pass_count);
|
2020-12-15 14:09:42 +00:00
|
|
|
}
|
2020-07-06 14:28:09 +00:00
|
|
|
}
|
2021-09-07 14:43:50 +00:00
|
|
|
|
2021-11-13 14:56:42 +00:00
|
|
|
void SerializeTAContext(Serializer& ser)
|
2021-09-07 14:43:50 +00:00
|
|
|
{
|
2022-01-29 17:39:38 +00:00
|
|
|
ser << (u32)ctx_list.size();
|
|
|
|
int curCtx = -1;
|
|
|
|
for (const auto& ctx : ctx_list)
|
|
|
|
{
|
2022-01-31 19:40:09 +00:00
|
|
|
if (ctx == ::ta_ctx)
|
2022-01-29 17:39:38 +00:00
|
|
|
curCtx = (int)(&ctx - &ctx_list[0]);
|
|
|
|
serializeContext(ser, ctx);
|
|
|
|
}
|
|
|
|
ser << curCtx;
|
2021-11-13 14:56:42 +00:00
|
|
|
}
|
2022-01-29 17:39:38 +00:00
|
|
|
|
2021-11-13 14:56:42 +00:00
|
|
|
void DeserializeTAContext(Deserializer& deser)
|
2021-09-07 14:43:50 +00:00
|
|
|
{
|
|
|
|
if (::ta_ctx != nullptr)
|
|
|
|
SetCurrentTARC(TACTX_NONE);
|
2022-01-29 17:39:38 +00:00
|
|
|
if (deser.version() >= Deserializer::V25)
|
|
|
|
{
|
|
|
|
u32 listSize;
|
|
|
|
deser >> listSize;
|
|
|
|
for (const auto& ctx : ctx_list)
|
|
|
|
tactx_Recycle(ctx);
|
|
|
|
ctx_list.clear();
|
|
|
|
for (u32 i = 0; i < listSize; i++)
|
|
|
|
{
|
|
|
|
TA_context *ctx;
|
|
|
|
deserializeContext(deser, &ctx);
|
|
|
|
}
|
|
|
|
int curCtx;
|
|
|
|
deser >> curCtx;
|
|
|
|
if (curCtx != -1)
|
|
|
|
SetCurrentTARC(ctx_list[curCtx]->Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TA_context *ta_cur_ctx;
|
2021-11-13 14:56:42 +00:00
|
|
|
deserializeContext(deser, &ta_cur_ctx);
|
2022-01-29 17:39:38 +00:00
|
|
|
if (ta_cur_ctx != nullptr)
|
|
|
|
SetCurrentTARC(ta_cur_ctx->Address);
|
|
|
|
if (deser.version() >= Deserializer::V20)
|
|
|
|
deserializeContext(deser, &ta_cur_ctx);
|
|
|
|
}
|
2021-09-07 14:43:50 +00:00
|
|
|
}
|