mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 12:51:42 +00:00
Initial work for async PSO.
This commit is contained in:
parent
3258d92bd3
commit
6351de36b6
1 changed files with 177 additions and 0 deletions
|
|
@ -4171,6 +4171,181 @@ void MotionBlurPrevInvViewProjectionMidAsmHook(PPCRegister& r10)
|
||||||
mtxProjection[14] = -mtxProjection[14];
|
mtxProjection[14] = -mtxProjection[14];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <Hedgehog/MirageCore/RenderData/hhMaterialData.h>
|
||||||
|
#include <Hedgehog/MirageCore/RenderData/hhMeshData.h>
|
||||||
|
#include <Hedgehog/MirageCore/RenderData/hhModelData.h>
|
||||||
|
#include <Hedgehog/MirageCore/RenderData/hhNodeGroupModelData.h>
|
||||||
|
#include <Hedgehog/MirageCore/RenderData/hhTerrainModelData.h>
|
||||||
|
|
||||||
|
// Normally, we could delay setting IsMadeOne, but the game relies on that flag
|
||||||
|
// being present to handle load priority. To work around that, we can prevent
|
||||||
|
// IsMadeAll from being set until the compilation is finished. Time for a custom flag!
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
eDatabaseDataFlags_CompilingPipelines = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
static moodycamel::BlockingConcurrentQueue<Hedgehog::Database::CDatabaseData*> g_readyModelQueue;
|
||||||
|
|
||||||
|
static void PipelineCompilerThread()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Hedgehog::Database::CDatabaseData* databaseData;
|
||||||
|
g_readyModelQueue.wait_dequeue(databaseData);
|
||||||
|
|
||||||
|
databaseData->m_Flags &= ~eDatabaseDataFlags_CompilingPipelines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::thread g_pipelineCompilerThread(PipelineCompilerThread);
|
||||||
|
|
||||||
|
static Mutex g_pendingModelMutex;
|
||||||
|
static std::vector<Hedgehog::Database::CDatabaseData*> g_pendingModelQueue;
|
||||||
|
|
||||||
|
static constexpr uint32_t MODEL_DATA_VFTABLE = 0x82073A44;
|
||||||
|
static constexpr uint32_t TERRAIN_MODEL_DATA_VFTABLE = 0x8211D25C;
|
||||||
|
|
||||||
|
// CModelData::CheckMadeAll
|
||||||
|
PPC_FUNC_IMPL(__imp__sub_82E2EFB0);
|
||||||
|
PPC_FUNC(sub_82E2EFB0)
|
||||||
|
{
|
||||||
|
if (reinterpret_cast<Hedgehog::Database::CDatabaseData*>(base + ctx.r3.u32)->m_Flags & eDatabaseDataFlags_CompilingPipelines)
|
||||||
|
{
|
||||||
|
ctx.r3.u64 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__imp__sub_82E2EFB0(ctx, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTerrainModelData::CheckMadeAll
|
||||||
|
PPC_FUNC_IMPL(__imp__sub_82E243D8);
|
||||||
|
PPC_FUNC(sub_82E243D8)
|
||||||
|
{
|
||||||
|
if (reinterpret_cast<Hedgehog::Database::CDatabaseData*>(base + ctx.r3.u32)->m_Flags & eDatabaseDataFlags_CompilingPipelines)
|
||||||
|
{
|
||||||
|
ctx.r3.u64 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__imp__sub_82E243D8(ctx, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMadeOne(Hedgehog::Database::CDatabaseData* databaseData)
|
||||||
|
{
|
||||||
|
if (databaseData->m_pVftable.ptr == MODEL_DATA_VFTABLE ||
|
||||||
|
databaseData->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE)
|
||||||
|
{
|
||||||
|
databaseData->m_Flags |= eDatabaseDataFlags_CompilingPipelines;
|
||||||
|
|
||||||
|
std::lock_guard lock(g_pendingModelMutex);
|
||||||
|
g_pendingModelQueue.push_back(databaseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
databaseData->m_Flags |= Hedgehog::Database::eDatabaseDataFlags_IsMadeOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData)
|
||||||
|
{
|
||||||
|
return meshData->IsMadeOne() && (meshData->m_spMaterial.get() == nullptr || meshData->m_spMaterial->IsMadeOne());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool CheckMadeAll(const T& modelData)
|
||||||
|
{
|
||||||
|
for (auto& meshGroup : modelData.m_NodeGroupModels)
|
||||||
|
{
|
||||||
|
for (auto& mesh : meshGroup->m_OpaqueMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& mesh : meshGroup->m_TransparentMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& mesh : meshGroup->m_PunchThroughMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& specialMeshGroup : meshGroup->m_SpecialMeshGroups)
|
||||||
|
{
|
||||||
|
for (auto& mesh : specialMeshGroup)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& mesh : modelData.m_OpaqueMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& mesh : modelData.m_TransparentMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& mesh : modelData.m_PunchThroughMeshes)
|
||||||
|
{
|
||||||
|
if (!CheckMadeAll(mesh.get()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ModelConsumerThread()
|
||||||
|
{
|
||||||
|
std::vector<Hedgehog::Database::CDatabaseData*> localPendingModelQueue;
|
||||||
|
|
||||||
|
// TODO: This sucks
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard lock(g_pendingModelMutex);
|
||||||
|
localPendingModelQueue.insert(localPendingModelQueue.end(), g_pendingModelQueue.begin(), g_pendingModelQueue.end());
|
||||||
|
g_pendingModelQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = localPendingModelQueue.begin(); it != localPendingModelQueue.end();)
|
||||||
|
{
|
||||||
|
bool ready = false;
|
||||||
|
|
||||||
|
if ((*it)->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE)
|
||||||
|
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CTerrainModelData*>(*it));
|
||||||
|
else
|
||||||
|
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CModelData*>(*it));
|
||||||
|
|
||||||
|
if (ready)
|
||||||
|
{
|
||||||
|
g_readyModelQueue.enqueue(*it);
|
||||||
|
it = localPendingModelQueue.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::thread g_modelConsumerThread(ModelConsumerThread);
|
||||||
|
|
||||||
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
|
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
|
||||||
|
|
||||||
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
|
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
|
||||||
|
|
@ -4236,6 +4411,8 @@ GUEST_FUNCTION_HOOK(sub_82E9EE38, SetResolution);
|
||||||
|
|
||||||
GUEST_FUNCTION_HOOK(sub_82AE2BF8, ScreenShaderInit);
|
GUEST_FUNCTION_HOOK(sub_82AE2BF8, ScreenShaderInit);
|
||||||
|
|
||||||
|
GUEST_FUNCTION_HOOK(sub_82E06CB8, SetMadeOne);
|
||||||
|
|
||||||
GUEST_FUNCTION_STUB(sub_822C15D8);
|
GUEST_FUNCTION_STUB(sub_822C15D8);
|
||||||
GUEST_FUNCTION_STUB(sub_822C1810);
|
GUEST_FUNCTION_STUB(sub_822C1810);
|
||||||
GUEST_FUNCTION_STUB(sub_82BD97A8);
|
GUEST_FUNCTION_STUB(sub_82BD97A8);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue