Async resource build fixes

This commit is contained in:
Jack Andersen 2016-03-31 15:00:37 -10:00
parent bc6ba1141d
commit 9fcce94a7a
10 changed files with 169 additions and 99 deletions

View File

@ -436,6 +436,46 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
}
lk.unlock();
auto asyncSearch = m_asyncLoadList.find(tag);
if (asyncSearch != m_asyncLoadList.end())
{
/* Async spinloop */
AsyncTask& task = asyncSearch->second;
task.EnsurePath(task.x0_tag, search->second);
/* Pump load pipeline (cooking if needed) */
while (!task.AsyncPump()) {std::this_thread::sleep_for(std::chrono::milliseconds(2));}
if (task.m_complete)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
{
newObj = m_factoryMgr.MakeObjectFromMemory(tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
*task.xc_targetPtr = newObj.get();
Log.report(logvisor::Warning, "spin-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return newObj;
}
Log.report(logvisor::Error, "unable to spin-build %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return {};
}
/* Fall-back to sync build */
return BuildSync(tag, search->second, paramXfer);
}
@ -545,8 +585,22 @@ void ProjectResourceFactoryBase::AsyncIdle()
if (task.m_complete)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
{
newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
*task.xc_targetPtr = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer).release();
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
*task.xc_targetPtr = newObj.release();
Log.report(logvisor::Info, "async-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
}
it = m_asyncLoadList.erase(it);
continue;

View File

@ -24,7 +24,7 @@ namespace urde
ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc)
: ProjectResourceFactoryBase(clientProc)
{
m_factoryMgr.AddFactory(FOURCC('TXTR'), FFactoryFunc(FTextureFactory));
m_factoryMgr.AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory));
m_factoryMgr.AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory));
m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame));
m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory));

View File

@ -21,6 +21,7 @@ namespace urde
void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
{
m_modelTest = objStore.GetObj("CMDL_GameCube");
m_modelTest.Lock();
//m_partGenDesc = objStore.GetObj({hecl::FOURCC('PART'), 0x972A5CD2});
m_partGenDesc = objStore.GetObj("BusterSparks");
@ -58,9 +59,16 @@ void ViewManager::ParticleView::resized(const boo::SWindowRect& root, const boo:
void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
{
if (m_vm.m_modelTest)
if (m_vm.m_modelTest.IsLoaded())
{
CModelFlags flags;
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
CGraphics::SetViewPointMatrix(zeus::CTransform::Identity() + zeus::CVector3f(0.f, -10.f, 0.f));
boo::SWindowRect windowRect = m_vm.m_mainWindow->getWindowFrame();
float aspect = windowRect.size[0] / float(windowRect.size[1]);
CGraphics::SetPerspective(55.0, aspect, 0.001f, 1000.f);
m_vm.m_modelTest->Draw(flags);
}
if (m_vm.m_partGen)
@ -70,11 +78,11 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
if (m_vm.m_partGen->IsSystemDeletable())
m_vm.m_partGen->Reset();
urde::CGraphics::SetModelMatrix(zeus::CTransform::Identity());
urde::CGraphics::SetViewPointMatrix(zeus::CTransform::Identity() + zeus::CVector3f(0.f, -10.f, 0.f));
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
CGraphics::SetViewPointMatrix(zeus::CTransform::Identity() + zeus::CVector3f(0.f, -10.f, 0.f));
boo::SWindowRect windowRect = m_vm.m_mainWindow->getWindowFrame();
float aspect = windowRect.size[0] / float(windowRect.size[1]);
urde::CGraphics::SetPerspective(55.0, aspect, 0.001f, 1000.f);
CGraphics::SetPerspective(55.0, aspect, 0.001f, 1000.f);
//gfxQ->clearTarget(false, true);
m_vm.m_partGen->Render();

View File

@ -48,8 +48,8 @@ class ViewManager : public specter::IViewManager
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
std::unique_ptr<ParticleView> m_particleView;
urde::TLockedToken<CModel> m_modelTest;
urde::TLockedToken<CGenDescription> m_partGenDesc;
urde::TCachedToken<CModel> m_modelTest;
urde::TCachedToken<CGenDescription> m_partGenDesc;
std::unique_ptr<CElementGen> m_partGen;
std::unique_ptr<CLineRenderer> m_lineRenderer;
std::unique_ptr<CMoviePlayer> m_moviePlayer;

View File

@ -19,18 +19,12 @@ CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXf
if (iter != x4_resources.end())
return CToken(iter->second);
// TODO: There is some logic missing here, need to figure out what it's doing
CObjectReference* ret = new CObjectReference(*this, x30_factory.Build(tag, paramXfer), tag, paramXfer);
if (ret->GetObject())
{
CObjectReference* ret = new CObjectReference(*this, std::unique_ptr<IObj>(), tag, paramXfer);
x4_resources.push_back(std::make_pair<SObjectTag, CObjectReference*>((SObjectTag)tag, std::move(ret)));
return CToken(ret);
}
delete ret;
return CToken();
}
CToken CSimplePool::GetObj(const SObjectTag& tag)
{
return GetObj(tag, x34_paramXfer);

View File

@ -16,6 +16,7 @@ class IObjectStore;
class CObjectReference
{
friend class CToken;
friend class CSimplePool;
u16 x0_refCount = 0;
u16 x2_lockCount = 0;
bool x3_loading = false; /* Rightmost bit of lockCount */
@ -23,7 +24,23 @@ class CObjectReference
IObjectStore* xC_objectStore = nullptr;
IObj* x10_object = nullptr;
CVParamTransfer x14_params;
public:
/** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset.
* Reaching 0 indicates the CToken should delete the CObjectReference */
u16 RemoveReference()
{
--x0_refCount;
if (x0_refCount == 0)
{
if (x10_object)
Unload();
if (IsLoading())
CancelLoad();
xC_objectStore->ObjectUnreferenced(x4_objTag);
}
return x0_refCount;
}
CObjectReference(IObjectStore& objStore, std::unique_ptr<IObj>&& obj,
const SObjectTag& objTag, CVParamTransfer buildParams)
: x4_objTag(objTag), xC_objectStore(&objStore),
@ -61,21 +78,6 @@ public:
}
}
/** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset.
* Reaching 0 indicates the CToken should delete the CObjectReference */
u16 RemoveReference()
{
--x0_refCount;
if (x0_refCount == 0)
{
if (x10_object)
Unload();
if (IsLoading())
CancelLoad();
xC_objectStore->ObjectUnreferenced(x4_objTag);
}
return x0_refCount;
}
void CancelLoad()
{
if (xC_objectStore && IsLoading())
@ -108,6 +110,8 @@ public:
{
return x4_objTag;
}
public:
~CObjectReference()
{
if (x10_object)
@ -122,8 +126,25 @@ public:
* (default/empty constructor, move constructor/assign) */
class CToken
{
friend class CSimplePool;
CObjectReference* x0_objRef = nullptr;
bool x4_lockHeld = false;
void RemoveRef()
{
if (x0_objRef && x0_objRef->RemoveReference() == 0)
{
std::default_delete<CObjectReference>()(x0_objRef);
x0_objRef = nullptr;
}
}
CToken(CObjectReference* obj)
{
x0_objRef = obj;
++x0_objRef->x0_refCount;
}
public:
/* Added to test for non-null state */
operator bool() const {return x0_objRef != nullptr;}
@ -150,14 +171,6 @@ public:
return false;
return x0_objRef->IsLoaded();
}
void RemoveRef()
{
if (x0_objRef && x0_objRef->RemoveReference() == 0)
{
std::default_delete<CObjectReference>()(x0_objRef);
x0_objRef = nullptr;
}
}
IObj* GetObj()
{
if (!x0_objRef)
@ -217,11 +230,6 @@ public:
++x0_objRef->x0_refCount;
Lock();
}
CToken(CObjectReference* obj)
{
x0_objRef = obj;
++x0_objRef->x0_refCount;
}
const SObjectTag* GetObjectTag() const
{
if (!x0_objRef)

View File

@ -156,6 +156,7 @@ zeus::CMatrix4f CGraphics::CalculatePerspectiveMatrix(float fovy, float aspect,
zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix()
{
CProjectionState& ref = g_Proj;
float rml = g_Proj.x8_right - g_Proj.x4_left;
float rpl = g_Proj.x8_right + g_Proj.x4_left;
float tmb = g_Proj.xc_top - g_Proj.x10_bottom;

View File

@ -116,8 +116,6 @@ void CBooModel::UnlockTextures() const
}
void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const
{
if (TryLockTextures())
{
const CBooSurface* surf = x3c_firstSortedSurface;
while (surf)
@ -126,11 +124,8 @@ void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const
surf = surf->m_next;
}
}
}
void CBooModel::DrawNormalSurfaces(const CModelFlags& flags) const
{
if (TryLockTextures())
{
const CBooSurface* surf = x38_firstUnsortedSurface;
while (surf)
@ -139,14 +134,9 @@ void CBooModel::DrawNormalSurfaces(const CModelFlags& flags) const
surf = surf->m_next;
}
}
}
void CBooModel::DrawSurfaces(const CModelFlags& flags) const
{
if (!(flags.m_flags & 0x4))
if (!TryLockTextures())
return;
const CBooSurface* surf = x38_firstUnsortedSurface;
while (surf)
{
@ -299,22 +289,31 @@ void CBooModel::UpdateUniformData() const
}
void CBooModel::DrawAlpha(const CModelFlags& flags) const
{
if (TryLockTextures())
{
UpdateUniformData();
DrawAlphaSurfaces(flags);
}
}
void CBooModel::DrawNormal(const CModelFlags& flags) const
{
if (TryLockTextures())
{
UpdateUniformData();
DrawNormalSurfaces(flags);
}
}
void CBooModel::Draw(const CModelFlags& flags) const
{
if (TryLockTextures())
{
UpdateUniformData();
DrawSurfaces(flags);
}
}
static const u8* MemoryFromPartData(const u8*& dataCur, const s32*& secSizeCur)
{
@ -378,7 +377,7 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 dataLen, IObjectStore* store)
{
hecl::Runtime::ShaderTag tag(mat.heclIr,
hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount,
0, mat.uvAnims.size(), true, true, true);
0, mat.uvAnims.size(), false, false, true);
matSet.m_shaders.push_back(CGraphics::g_ShaderCacheMgr->buildShader(tag, mat.heclIr, "CMDL", ctx));
}
}
@ -403,7 +402,7 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 dataLen, IObjectStore* store)
hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5]));
x28_modelInst = std::make_unique<CBooModel>(&x8_surfaces, x18_matSets[0],
m_vtxFmt, m_vbo, m_ibo,
aabb, flags & 0x2, true);
aabb, flags & 0x2, false);
}
void CBooModel::SShader::UnlockTextures()
@ -465,7 +464,8 @@ CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
const urde::CVParamTransfer& vparms)
{
IObjectStore* store = static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam();
return TToken<CModel>::GetIObjObjectFor(std::make_unique<CModel>(std::move(in), len, store));
CFactoryFnReturn ret = TToken<CModel>::GetIObjObjectFor(std::make_unique<CModel>(std::move(in), len, store));
return ret;
}
}

View File

@ -34,10 +34,10 @@ class CTexture
void BuildRGB5A3FromGCN(CInputStream& in);
void BuildRGBA8FromGCN(CInputStream& in);
void BuildDXT1FromGCN(CInputStream& in);
void BuildRGBA8(CInputStream& in);
void BuildRGBA8(const void* data);
public:
CTexture(CInputStream& in);
CTexture(std::unique_ptr<u8[]>&& in, u32 length);
enum class EClampMode
{
None,
@ -50,7 +50,9 @@ public:
boo::ITexture* GetBooTexture() {return m_booTex;}
};
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms);
CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>&& in, u32 len,
const urde::CVParamTransfer& vparms);
}

View File

@ -648,63 +648,64 @@ void CTexture::BuildDXT1FromGCN(CInputStream& in)
});
}
void CTexture::BuildRGBA8(CInputStream& in)
void CTexture::BuildRGBA8(const void* data)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<atInt8[]> buf = in.readBytes(texelCount * 4);
m_booToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4);
data, texelCount * 4);
return true;
});
}
CTexture::CTexture(CInputStream& in)
CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length)
{
x0_fmt = ETexelFormat(in.readUint32Big());
x4_w = in.readUint16Big();
x6_h = in.readUint16Big();
x8_mips = in.readUint32Big();
std::unique_ptr<u8[]> owned = std::move(in);
athena::io::MemoryReader r(owned.get(), length);
x0_fmt = ETexelFormat(r.readUint32Big());
x4_w = r.readUint16Big();
x6_h = r.readUint16Big();
x8_mips = r.readUint32Big();
switch (x0_fmt)
{
case ETexelFormat::I4:
BuildI4FromGCN(in);
BuildI4FromGCN(r);
break;
case ETexelFormat::I8:
BuildI8FromGCN(in);
BuildI8FromGCN(r);
break;
case ETexelFormat::IA4:
BuildIA4FromGCN(in);
BuildIA4FromGCN(r);
break;
case ETexelFormat::IA8:
BuildIA8FromGCN(in);
BuildIA8FromGCN(r);
break;
case ETexelFormat::C4:
BuildC4FromGCN(in);
BuildC4FromGCN(r);
break;
case ETexelFormat::C8:
BuildC8FromGCN(in);
BuildC8FromGCN(r);
break;
case ETexelFormat::C14X2:
BuildC14X2FromGCN(in);
BuildC14X2FromGCN(r);
break;
case ETexelFormat::RGB565:
BuildRGB565FromGCN(in);
BuildRGB565FromGCN(r);
break;
case ETexelFormat::RGB5A3:
BuildRGB5A3FromGCN(in);
BuildRGB5A3FromGCN(r);
break;
case ETexelFormat::RGBA8:
BuildRGBA8FromGCN(in);
BuildRGBA8FromGCN(r);
break;
case ETexelFormat::CMPR:
BuildDXT1FromGCN(in);
BuildDXT1FromGCN(r);
break;
case ETexelFormat::RGBA8PC:
BuildRGBA8(in);
BuildRGBA8(owned.get() + 12);
break;
default:
Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt));
@ -716,9 +717,11 @@ void CTexture::Load(int slot, EClampMode clamp) const
}
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms)
CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>&& in, u32 len,
const urde::CVParamTransfer& vparms)
{
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(in));
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(std::move(in), len));
}
}