From 1bcf0aacd8ada0296c15f1127f3f0776b1e33509 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:25:17 +0300 Subject: [PATCH] Safety improvements. --- UnleashedRecomp/gpu/video.cpp | 99 +++++++++++++++++++----------- UnleashedRecompLib/config/SWA.toml | 4 +- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 8efc3c0b..9e4d44f7 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -3523,6 +3524,8 @@ static void ProcSetPixelShader(const RenderCommand& cmd) static std::thread g_renderThread([] { + GuestThread::SetThreadName(GetCurrentThreadId(), "Render Thread"); + RenderCommand commands[32]; while (true) @@ -3890,7 +3893,7 @@ static RenderFormat ConvertDXGIFormat(ddspp::DXGIFormat format) 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; 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 TERRAIN_MODEL_DATA_VFTABLE = 0x8211D25C; -static moodycamel::BlockingConcurrentQueue> g_loadedModelQueue; -static std::atomic g_pendingModelCount; +static moodycamel::BlockingConcurrentQueue> g_compilingModelQueue; +static std::atomic g_compilingModelCount; // 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. @@ -4442,13 +4445,15 @@ static void CompileMeshPipelines(const T& modelData, const CompilationArgs& args static void PipelineCompilerThread() { + GuestThread::SetThreadName(GetCurrentThreadId(), "Pipeline Compiler Thread"); + uint8_t* stack = nullptr; PPCContext ppcContext{}; while (true) { boost::shared_ptr databaseData; - g_loadedModelQueue.wait_dequeue(databaseData); + g_compilingModelQueue.wait_dequeue(databaseData); if (stack == nullptr) { @@ -4471,8 +4476,8 @@ static void PipelineCompilerThread() databaseData->m_Flags &= ~eDatabaseDataFlags_CompilingPipelines; - if ((--g_pendingModelCount) == 0) - g_pendingModelCount.notify_all(); + if ((--g_compilingModelCount) == 0) + g_compilingModelCount.notify_all(); } g_userHeap.Free(stack); @@ -4480,9 +4485,6 @@ static void PipelineCompilerThread() static std::thread g_pipelineCompilerThread(PipelineCompilerThread); -static Mutex g_pendingModelMutex; -static std::vector> g_pendingModelQueue; - // Hedgehog::Database::WaitForArchiveLoadFinish PPC_FUNC_IMPL(__imp__sub_82E0C288); PPC_FUNC(sub_82E0C288) @@ -4491,8 +4493,8 @@ PPC_FUNC(sub_82E0C288) // Wait for pipeline compilations to finish. uint32_t value; - while ((value = g_pendingModelCount.load()) != 0) - g_pendingModelCount.wait(value); + while ((value = g_compilingModelCount.load()) != 0) + g_compilingModelCount.wait(value); } // CModelData::CheckMadeAll @@ -4523,16 +4525,28 @@ PPC_FUNC(sub_82E243D8) } } -void GetModelDataMidAsmHook(PPCRegister& r1) +static Mutex g_pendingModelMutex; +static std::vector> g_pendingModelQueue; +static std::atomic g_pendingModelCount; + +void GetModelDataMidAsmHook(PPCRegister& r1, PPCRegister& r31) { - auto databaseData = *reinterpret_cast*>( + auto& databaseData = *reinterpret_cast*>( g_memory.Translate(r1.u32 + 0x58)); - ++g_pendingModelCount; - databaseData->m_Flags |= eDatabaseDataFlags_CompilingPipelines; - - std::lock_guard lock(g_pendingModelMutex); - g_pendingModelQueue.push_back(databaseData); + if (!databaseData->IsMadeOne() && r31.u32 != NULL) + { + ++g_compilingModelCount; + databaseData->m_Flags |= eDatabaseDataFlags_CompilingPipelines; + + { + std::lock_guard lock(g_pendingModelMutex); + g_pendingModelQueue.push_back(databaseData); + } + + ++g_pendingModelCount; + g_pendingModelCount.notify_all(); + } } static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData) @@ -4543,6 +4557,9 @@ static bool CheckMadeAll(Hedgehog::Mirage::CMeshData* meshData) template static bool CheckMadeAll(const T& modelData) { + if (!modelData.IsMadeOne()) + return false; + for (auto& meshGroup : modelData.m_NodeGroupModels) { for (auto& mesh : meshGroup->m_OpaqueMeshes) @@ -4596,38 +4613,50 @@ static bool CheckMadeAll(const T& modelData) static void ModelConsumerThread() { + GuestThread::SetThreadName(GetCurrentThreadId(), "Model Consumer Thread"); + std::vector> localPendingModelQueue; - // TODO: This sucks 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); localPendingModelQueue.insert(localPendingModelQueue.end(), g_pendingModelQueue.begin(), g_pendingModelQueue.end()); g_pendingModelQueue.clear(); } - for (auto it = localPendingModelQueue.begin(); it != localPendingModelQueue.end();) + bool allHandled = true; + + for (auto& pendingModel : localPendingModelQueue) { - bool ready = false; - - if ((*it)->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE) - ready = CheckMadeAll(*reinterpret_cast(it->get())); - else - ready = CheckMadeAll(*reinterpret_cast(it->get())); - - if (ready) + if (pendingModel.get() != nullptr) { - g_loadedModelQueue.enqueue(*it); - it = localPendingModelQueue.erase(it); - } - else - { - ++it; + bool ready = false; + + if (pendingModel->m_pVftable.ptr == TERRAIN_MODEL_DATA_VFTABLE) + ready = CheckMadeAll(*reinterpret_cast(pendingModel.get())); + else + ready = CheckMadeAll(*reinterpret_cast(pendingModel.get())); + + if (ready) + { + g_compilingModelQueue.enqueue(std::move(pendingModel)); + --g_pendingModelCount; + } + else + { + allHandled = false; + } } } - Sleep(5); + if (allHandled) + localPendingModelQueue.clear(); } } diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index cc98bba7..c6f34255 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -431,9 +431,9 @@ registers = ["r10"] [[midasm_hook]] name = "GetModelDataMidAsmHook" address = 0x82E38688 -registers = ["r1"] +registers = ["r1", "r31"] [[midasm_hook]] name = "GetModelDataMidAsmHook" address = 0x82E39650 -registers = ["r1"] +registers = ["r1", "r31"]