2019-12-22 20:04:07 +00:00
|
|
|
#include "Runtime/CResFactory.hpp"
|
|
|
|
|
|
|
|
#include "Runtime/CSimplePool.hpp"
|
|
|
|
#include "Runtime/CStopwatch.hpp"
|
2021-04-03 16:48:39 +00:00
|
|
|
#include "optick.h"
|
2015-08-17 22:05:00 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
namespace metaforce {
|
2017-10-27 10:10:32 +00:00
|
|
|
static logvisor::Module Log("CResFactory");
|
2015-08-17 22:05:00 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CResFactory::AddToLoadList(SLoadingData&& data) {
|
2020-03-07 08:56:12 +00:00
|
|
|
const SObjectTag tag = data.x0_tag;
|
|
|
|
m_loadMap.insert_or_assign(tag, m_loadList.insert(m_loadList.end(), std::move(data)));
|
2015-08-22 01:58:41 +00:00
|
|
|
}
|
2017-10-26 10:09:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CFactoryFnReturn CResFactory::BuildSync(const SObjectTag& tag, const CVParamTransfer& xfer, CObjectReference* selfRef) {
|
|
|
|
CFactoryFnReturn ret;
|
|
|
|
if (x5c_factoryMgr.CanMakeMemory(tag)) {
|
|
|
|
std::unique_ptr<uint8_t[]> data;
|
|
|
|
int size = 0;
|
|
|
|
x4_loader.LoadMemResourceSync(tag, data, &size);
|
|
|
|
if (size)
|
|
|
|
ret = x5c_factoryMgr.MakeObjectFromMemory(tag, std::move(data), size, x4_loader.GetResourceCompression(tag), xfer,
|
|
|
|
selfRef);
|
2017-10-26 10:09:51 +00:00
|
|
|
else
|
2018-12-08 05:30:43 +00:00
|
|
|
ret = std::make_unique<TObjOwnerDerivedFromIObjUntyped>(nullptr);
|
|
|
|
} else {
|
|
|
|
if (auto rp = x4_loader.LoadNewResourceSync(tag, nullptr))
|
|
|
|
ret = x5c_factoryMgr.MakeObject(tag, *rp, xfer, selfRef);
|
|
|
|
else
|
|
|
|
ret = std::make_unique<TObjOwnerDerivedFromIObjUntyped>(nullptr);
|
|
|
|
}
|
2020-04-11 22:51:39 +00:00
|
|
|
Log.report(logvisor::Warning, FMT_STRING("sync-built {}"), tag);
|
2018-12-08 05:30:43 +00:00
|
|
|
return ret;
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
bool CResFactory::PumpResource(SLoadingData& data) {
|
2021-04-03 16:48:39 +00:00
|
|
|
OPTICK_EVENT();
|
2018-12-08 05:30:43 +00:00
|
|
|
if (data.x8_dvdReq && data.x8_dvdReq->IsComplete()) {
|
|
|
|
data.x8_dvdReq.reset();
|
|
|
|
*data.xc_targetPtr =
|
|
|
|
x5c_factoryMgr.MakeObjectFromMemory(data.x0_tag, std::move(data.x10_loadBuffer), data.x14_resSize,
|
|
|
|
data.m_compressed, data.x18_cvXfer, data.m_selfRef);
|
2020-04-11 22:51:39 +00:00
|
|
|
Log.report(logvisor::Info, FMT_STRING("async-built {}"), data.x0_tag);
|
2018-12-08 05:30:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
std::unique_ptr<IObj> CResFactory::Build(const SObjectTag& tag, const CVParamTransfer& xfer,
|
|
|
|
CObjectReference* selfRef) {
|
|
|
|
auto search = m_loadMap.find(tag);
|
|
|
|
if (search != m_loadMap.end()) {
|
|
|
|
while (!PumpResource(*search->second) || !search->second->xc_targetPtr) {}
|
|
|
|
std::unique_ptr<IObj> ret = std::move(*search->second->xc_targetPtr);
|
|
|
|
m_loadList.erase(search->second);
|
|
|
|
m_loadMap.erase(search);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return BuildSync(tag, xfer, selfRef);
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CResFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& xfer, std::unique_ptr<IObj>* target,
|
2018-12-08 05:30:43 +00:00
|
|
|
CObjectReference* selfRef) {
|
|
|
|
auto search = m_loadMap.find(tag);
|
|
|
|
if (search == m_loadMap.end()) {
|
|
|
|
SLoadingData data(tag, target, xfer, x4_loader.GetResourceCompression(tag), selfRef);
|
|
|
|
data.x14_resSize = x4_loader.ResourceSize(tag);
|
2022-02-19 13:04:45 +00:00
|
|
|
if (data.x14_resSize != 0) {
|
2018-12-08 05:30:43 +00:00
|
|
|
data.x10_loadBuffer = std::unique_ptr<u8[]>(new u8[data.x14_resSize]);
|
|
|
|
data.x8_dvdReq = x4_loader.LoadResourceAsync(tag, data.x10_loadBuffer.get());
|
|
|
|
AddToLoadList(std::move(data));
|
|
|
|
} else {
|
|
|
|
*target = std::make_unique<TObjOwnerDerivedFromIObjUntyped>(nullptr);
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2015-08-22 01:58:41 +00:00
|
|
|
}
|
2017-10-26 10:09:51 +00:00
|
|
|
|
2021-05-30 19:03:35 +00:00
|
|
|
bool CResFactory::AsyncIdle(std::chrono::nanoseconds target) {
|
2021-04-03 16:48:39 +00:00
|
|
|
OPTICK_EVENT();
|
2021-05-30 19:03:35 +00:00
|
|
|
if (m_loadList.empty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto startTime = std::chrono::high_resolution_clock::now();
|
|
|
|
do {
|
2018-12-08 05:30:43 +00:00
|
|
|
auto& task = m_loadList.front();
|
|
|
|
if (PumpResource(task)) {
|
|
|
|
m_loadMap.erase(task.x0_tag);
|
|
|
|
m_loadList.pop_front();
|
2021-05-30 19:03:35 +00:00
|
|
|
if (m_loadList.empty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
2021-05-30 19:40:08 +00:00
|
|
|
} while (std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startTime) <
|
2021-05-30 19:03:35 +00:00
|
|
|
target);
|
|
|
|
return true;
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CResFactory::CancelBuild(const SObjectTag& tag) {
|
|
|
|
auto search = m_loadMap.find(tag);
|
|
|
|
if (search != m_loadMap.end()) {
|
|
|
|
if (search->second->x8_dvdReq)
|
|
|
|
search->second->x8_dvdReq->PostCancelRequest();
|
|
|
|
m_loadList.erase(search->second);
|
|
|
|
m_loadMap.erase(search);
|
|
|
|
}
|
2017-10-26 10:09:51 +00:00
|
|
|
}
|
|
|
|
|
2019-03-09 08:58:27 +00:00
|
|
|
void CResFactory::LoadPersistentResources(CSimplePool& sp) {
|
|
|
|
const auto& paks = x4_loader.GetPaks();
|
2022-02-19 13:04:45 +00:00
|
|
|
for (const auto & pak : paks) {
|
|
|
|
if (!pak->IsWorldPak()) {
|
|
|
|
for (const CAssetId& id : pak->GetDepList()) {
|
2019-03-09 08:58:27 +00:00
|
|
|
SObjectTag tag(GetResourceTypeById(id), id);
|
|
|
|
m_nonWorldTokens.push_back(sp.GetObj(tag));
|
|
|
|
m_nonWorldTokens.back().Lock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
} // namespace metaforce
|