diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index a17e0469..39591892 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -58,6 +58,11 @@ bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs:: return false; } +void GPU::flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx) { + auto* gpumemory = Singleton::Instance(); + gpumemory->flushAllHeaps(ctx); +} + int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; for (const auto& heap : m_heaps) { @@ -106,6 +111,7 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); + objInfo.update_func = info.getUpdateFunc(); int index = static_cast(heap.objects.size()); HeapObject hobj{}; @@ -128,3 +134,55 @@ GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u6 } return heapBlock; } + +void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id) { + auto& heap = m_heaps[heap_id]; + + auto& heapObj = heap.objects[obj_id]; + auto& objInfo = heapObj.info; + bool need_update = false; + + if (submit_id > objInfo.submit_id) { + uint64_t hash[3] = {}; + + for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { + if (objInfo.check_hash) { + hash[i] = GPU::calculate_hash(reinterpret_cast(heapObj.block.virtual_addr[i]), heapObj.block.size[i]); + } else { + hash[i] = 0; + } + } + + for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { + if (objInfo.hash[i] != hash[i]) { + need_update = true; + objInfo.hash[i] = hash[i]; + } + } + + if (submit_id != UINT64_MAX) { + objInfo.submit_id = submit_id; + } + } + + if (need_update) { + objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj, heapObj.block.virtual_addr, heapObj.block.size, + heapObj.block.virtual_addr_num); + } +} + +void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) { + Lib::LockMutexGuard lock(m_mutex); + + int heap_id = 0; + for (auto& heap : m_heaps) { + int index = 0; + for (auto& heapObj : heap.objects) { + if (!heapObj.free) { + update(UINT64_MAX, ctx, heap_id, index); + } + index++; + } + heap_id++; + } +} diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 7690cd06..f7612649 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -11,51 +11,17 @@ class GPUObject; enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; - - struct GpuMemoryObject { MemoryObjectType objectType = MemoryObjectType::InvalidObj; void* obj = nullptr; }; -struct ObjInfo { - u64 obj_params[8] = {}; - GpuMemoryObject gpu_object; - u64 hash[3] = {}; - u64 submit_id = 0; - bool check_hash = false; - HLE::Libs::Graphics::VulkanMemory mem; -}; - struct HeapBlock { u64 virtual_addr[3] = {}; u64 size[3] = {}; int virtual_addr_num = 0; }; -struct HeapObject { - HeapBlock block; - ObjInfo info; - bool free = true; -}; - -struct MemoryHeap { - u64 allocated_virtual_addr = 0; - u64 allocated_size = 0; - std::vector objects; -}; - -class GPUMemory { - public: - GPUMemory() {} - virtual ~GPUMemory() {} - int getHeapId(u64 vaddr, u64 size); - Lib::Mutex m_mutex; - std::vector m_heaps; - void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, - const u64* size, int virtual_addr_num, const GPUObject& info); - HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); -}; class GPUObject { public: GPUObject() = default; @@ -74,9 +40,45 @@ class GPUObject { virtual update_func_t getUpdateFunc() const = 0; }; +struct ObjInfo { + u64 obj_params[8] = {}; + GpuMemoryObject gpu_object; + u64 hash[3] = {}; + u64 submit_id = 0; + bool check_hash = false; + HLE::Libs::Graphics::VulkanMemory mem; + GPU::GPUObject::update_func_t update_func = nullptr; +}; + +struct HeapObject { + HeapBlock block; + ObjInfo info; + bool free = true; +}; +struct MemoryHeap { + u64 allocated_virtual_addr = 0; + u64 allocated_size = 0; + std::vector objects; +}; + +class GPUMemory { + public: + GPUMemory() {} + virtual ~GPUMemory() {} + int getHeapId(u64 vaddr, u64 size); + Lib::Mutex m_mutex; + std::vector m_heaps; + void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, + const u64* size, int virtual_addr_num, const GPUObject& info); + HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); + void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id); + void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx); +}; + void memorySetAllocArea(u64 virtual_addr, u64 size); void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); u64 calculate_hash(const u08* buf, u64 size); bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); +void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/HLE/LibSceGnmDriver.cpp b/src/Core/PS4/HLE/LibSceGnmDriver.cpp index cc48ba45..9744b23f 100644 --- a/src/Core/PS4/HLE/LibSceGnmDriver.cpp +++ b/src/Core/PS4/HLE/LibSceGnmDriver.cpp @@ -3,6 +3,8 @@ #include "../Loader/Elf.h" #include #include +#include +#include namespace HLE::Libs::LibSceGnmDriver { @@ -88,7 +90,8 @@ namespace HLE::Libs::LibSceGnmDriver { void sceGnmDriverTraceInProgress(){} void sceGnmDriverTriggerCapture(){} void sceGnmEndWorkload(){} - void sceGnmFlushGarlic() { PRINT_DUMMY_FUNCTION_NAME(); + void sceGnmFlushGarlic() { PRINT_FUNCTION_NAME(); + GPU::flushGarlic(Emulator::getGraphicCtx()); } void sceGnmGetEqEventType(){} void sceGnmGetEqTimeStamp(){}