mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
Safety improvements.
This commit is contained in:
parent
8efdbf7c76
commit
1bcf0aacd8
2 changed files with 66 additions and 37 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
#include <kernel/heap.h>
|
#include <kernel/heap.h>
|
||||||
#include <cpu/code_cache.h>
|
#include <cpu/code_cache.h>
|
||||||
#include <cpu/guest_code.h>
|
#include <cpu/guest_code.h>
|
||||||
|
#include <cpu/guest_thread.h>
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
#include <xxHashMap.h>
|
#include <xxHashMap.h>
|
||||||
#include <shader/shader_cache.h>
|
#include <shader/shader_cache.h>
|
||||||
|
|
@ -3523,6 +3524,8 @@ static void ProcSetPixelShader(const RenderCommand& cmd)
|
||||||
|
|
||||||
static std::thread g_renderThread([]
|
static std::thread g_renderThread([]
|
||||||
{
|
{
|
||||||
|
GuestThread::SetThreadName(GetCurrentThreadId(), "Render Thread");
|
||||||
|
|
||||||
RenderCommand commands[32];
|
RenderCommand commands[32];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -3890,7 +3893,7 @@ static RenderFormat ConvertDXGIFormat(ddspp::DXGIFormat format)
|
||||||
|
|
||||||
static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32_t dataSize)
|
static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32_t dataSize)
|
||||||
{
|
{
|
||||||
if ((pictureData->flags & 0x1) == 0)
|
if ((pictureData->flags & 0x1) == 0 && data != nullptr)
|
||||||
{
|
{
|
||||||
ddspp::Descriptor ddsDesc;
|
ddspp::Descriptor ddsDesc;
|
||||||
if (ddspp::decode_header(data, ddsDesc) != ddspp::Error)
|
if (ddspp::decode_header(data, ddsDesc) != ddspp::Error)
|
||||||
|
|
@ -4243,8 +4246,8 @@ enum
|
||||||
static constexpr uint32_t MODEL_DATA_VFTABLE = 0x82073A44;
|
static constexpr uint32_t MODEL_DATA_VFTABLE = 0x82073A44;
|
||||||
static constexpr uint32_t TERRAIN_MODEL_DATA_VFTABLE = 0x8211D25C;
|
static constexpr uint32_t TERRAIN_MODEL_DATA_VFTABLE = 0x8211D25C;
|
||||||
|
|
||||||
static moodycamel::BlockingConcurrentQueue<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> g_loadedModelQueue;
|
static moodycamel::BlockingConcurrentQueue<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> g_compilingModelQueue;
|
||||||
static std::atomic<uint32_t> g_pendingModelCount;
|
static std::atomic<uint32_t> g_compilingModelCount;
|
||||||
|
|
||||||
// Having this separate, because I don't want to lock a mutex in the render thread before
|
// Having this separate, because I don't want to lock a mutex in the render thread before
|
||||||
// every single draw. Might be worth profiling to see if it actually has an impact and merge them.
|
// every single draw. Might be worth profiling to see if it actually has an impact and merge them.
|
||||||
|
|
@ -4442,13 +4445,15 @@ static void CompileMeshPipelines(const T& modelData, const CompilationArgs& args
|
||||||
|
|
||||||
static void PipelineCompilerThread()
|
static void PipelineCompilerThread()
|
||||||
{
|
{
|
||||||
|
GuestThread::SetThreadName(GetCurrentThreadId(), "Pipeline Compiler Thread");
|
||||||
|
|
||||||
uint8_t* stack = nullptr;
|
uint8_t* stack = nullptr;
|
||||||
PPCContext ppcContext{};
|
PPCContext ppcContext{};
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Hedgehog::Database::CDatabaseData> databaseData;
|
boost::shared_ptr<Hedgehog::Database::CDatabaseData> databaseData;
|
||||||
g_loadedModelQueue.wait_dequeue(databaseData);
|
g_compilingModelQueue.wait_dequeue(databaseData);
|
||||||
|
|
||||||
if (stack == nullptr)
|
if (stack == nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -4471,8 +4476,8 @@ static void PipelineCompilerThread()
|
||||||
|
|
||||||
databaseData->m_Flags &= ~eDatabaseDataFlags_CompilingPipelines;
|
databaseData->m_Flags &= ~eDatabaseDataFlags_CompilingPipelines;
|
||||||
|
|
||||||
if ((--g_pendingModelCount) == 0)
|
if ((--g_compilingModelCount) == 0)
|
||||||
g_pendingModelCount.notify_all();
|
g_compilingModelCount.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_userHeap.Free(stack);
|
g_userHeap.Free(stack);
|
||||||
|
|
@ -4480,9 +4485,6 @@ static void PipelineCompilerThread()
|
||||||
|
|
||||||
static std::thread g_pipelineCompilerThread(PipelineCompilerThread);
|
static std::thread g_pipelineCompilerThread(PipelineCompilerThread);
|
||||||
|
|
||||||
static Mutex g_pendingModelMutex;
|
|
||||||
static std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> g_pendingModelQueue;
|
|
||||||
|
|
||||||
// Hedgehog::Database::WaitForArchiveLoadFinish
|
// Hedgehog::Database::WaitForArchiveLoadFinish
|
||||||
PPC_FUNC_IMPL(__imp__sub_82E0C288);
|
PPC_FUNC_IMPL(__imp__sub_82E0C288);
|
||||||
PPC_FUNC(sub_82E0C288)
|
PPC_FUNC(sub_82E0C288)
|
||||||
|
|
@ -4491,8 +4493,8 @@ PPC_FUNC(sub_82E0C288)
|
||||||
|
|
||||||
// Wait for pipeline compilations to finish.
|
// Wait for pipeline compilations to finish.
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
while ((value = g_pendingModelCount.load()) != 0)
|
while ((value = g_compilingModelCount.load()) != 0)
|
||||||
g_pendingModelCount.wait(value);
|
g_compilingModelCount.wait(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CModelData::CheckMadeAll
|
// CModelData::CheckMadeAll
|
||||||
|
|
@ -4523,16 +4525,28 @@ PPC_FUNC(sub_82E243D8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetModelDataMidAsmHook(PPCRegister& r1)
|
static Mutex g_pendingModelMutex;
|
||||||
|
static std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> g_pendingModelQueue;
|
||||||
|
static std::atomic<uint32_t> g_pendingModelCount;
|
||||||
|
|
||||||
|
void GetModelDataMidAsmHook(PPCRegister& r1, PPCRegister& r31)
|
||||||
{
|
{
|
||||||
auto databaseData = *reinterpret_cast<boost::shared_ptr<Hedgehog::Database::CDatabaseData>*>(
|
auto& databaseData = *reinterpret_cast<boost::shared_ptr<Hedgehog::Database::CDatabaseData>*>(
|
||||||
g_memory.Translate(r1.u32 + 0x58));
|
g_memory.Translate(r1.u32 + 0x58));
|
||||||
|
|
||||||
++g_pendingModelCount;
|
if (!databaseData->IsMadeOne() && r31.u32 != NULL)
|
||||||
|
{
|
||||||
|
++g_compilingModelCount;
|
||||||
databaseData->m_Flags |= eDatabaseDataFlags_CompilingPipelines;
|
databaseData->m_Flags |= eDatabaseDataFlags_CompilingPipelines;
|
||||||
|
|
||||||
|
{
|
||||||
std::lock_guard lock(g_pendingModelMutex);
|
std::lock_guard lock(g_pendingModelMutex);
|
||||||
g_pendingModelQueue.push_back(databaseData);
|
g_pendingModelQueue.push_back(databaseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
++g_pendingModelCount;
|
||||||
|
g_pendingModelCount.notify_all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData)
|
static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData)
|
||||||
|
|
@ -4543,6 +4557,9 @@ static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool CheckMadeAll(const T& modelData)
|
static bool CheckMadeAll(const T& modelData)
|
||||||
{
|
{
|
||||||
|
if (!modelData.IsMadeOne())
|
||||||
|
return false;
|
||||||
|
|
||||||
for (auto& meshGroup : modelData.m_NodeGroupModels)
|
for (auto& meshGroup : modelData.m_NodeGroupModels)
|
||||||
{
|
{
|
||||||
for (auto& mesh : meshGroup->m_OpaqueMeshes)
|
for (auto& mesh : meshGroup->m_OpaqueMeshes)
|
||||||
|
|
@ -4596,38 +4613,50 @@ static bool CheckMadeAll(const T& modelData)
|
||||||
|
|
||||||
static void ModelConsumerThread()
|
static void ModelConsumerThread()
|
||||||
{
|
{
|
||||||
|
GuestThread::SetThreadName(GetCurrentThreadId(), "Model Consumer Thread");
|
||||||
|
|
||||||
std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> localPendingModelQueue;
|
std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> localPendingModelQueue;
|
||||||
|
|
||||||
// TODO: This sucks
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
// Wait for models to arrive.
|
||||||
|
uint32_t pendingModelCount;
|
||||||
|
while ((pendingModelCount = g_pendingModelCount.load()) == 0)
|
||||||
|
g_pendingModelCount.wait(pendingModelCount);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock(g_pendingModelMutex);
|
std::lock_guard lock(g_pendingModelMutex);
|
||||||
localPendingModelQueue.insert(localPendingModelQueue.end(), g_pendingModelQueue.begin(), g_pendingModelQueue.end());
|
localPendingModelQueue.insert(localPendingModelQueue.end(), g_pendingModelQueue.begin(), g_pendingModelQueue.end());
|
||||||
g_pendingModelQueue.clear();
|
g_pendingModelQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = localPendingModelQueue.begin(); it != localPendingModelQueue.end();)
|
bool allHandled = true;
|
||||||
|
|
||||||
|
for (auto& pendingModel : localPendingModelQueue)
|
||||||
|
{
|
||||||
|
if (pendingModel.get() != nullptr)
|
||||||
{
|
{
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
|
|
||||||
if ((*it)->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE)
|
if (pendingModel->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE)
|
||||||
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CTerrainModelData*>(it->get()));
|
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CTerrainModelData*>(pendingModel.get()));
|
||||||
else
|
else
|
||||||
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CModelData*>(it->get()));
|
ready = CheckMadeAll(*reinterpret_cast<Hedgehog::Mirage::CModelData*>(pendingModel.get()));
|
||||||
|
|
||||||
if (ready)
|
if (ready)
|
||||||
{
|
{
|
||||||
g_loadedModelQueue.enqueue(*it);
|
g_compilingModelQueue.enqueue(std::move(pendingModel));
|
||||||
it = localPendingModelQueue.erase(it);
|
--g_pendingModelCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++it;
|
allHandled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sleep(5);
|
if (allHandled)
|
||||||
|
localPendingModelQueue.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -431,9 +431,9 @@ registers = ["r10"]
|
||||||
[[midasm_hook]]
|
[[midasm_hook]]
|
||||||
name = "GetModelDataMidAsmHook"
|
name = "GetModelDataMidAsmHook"
|
||||||
address = 0x82E38688
|
address = 0x82E38688
|
||||||
registers = ["r1"]
|
registers = ["r1", "r31"]
|
||||||
|
|
||||||
[[midasm_hook]]
|
[[midasm_hook]]
|
||||||
name = "GetModelDataMidAsmHook"
|
name = "GetModelDataMidAsmHook"
|
||||||
address = 0x82E39650
|
address = 0x82E39650
|
||||||
registers = ["r1"]
|
registers = ["r1", "r31"]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue