Merge pull request #61 from GPUCode/stl-threads
core: Switch threading primitives to STL types
This commit is contained in:
commit
fed14ad4ed
|
@ -83,8 +83,6 @@ add_executable(shadps4
|
||||||
src/Core/PS4/Stubs.cpp
|
src/Core/PS4/Stubs.cpp
|
||||||
src/Core/PS4/Stubs.h
|
src/Core/PS4/Stubs.h
|
||||||
src/Core/PS4/Util/aerolib.cpp
|
src/Core/PS4/Util/aerolib.cpp
|
||||||
src/Lib/Threads.cpp
|
|
||||||
src/Lib/Threads.h
|
|
||||||
src/Core/PS4/HLE/Kernel/Objects/physical_memory.h
|
src/Core/PS4/HLE/Kernel/Objects/physical_memory.h
|
||||||
src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp
|
src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp
|
||||||
src/Util/string_util.cpp
|
src/Util/string_util.cpp
|
||||||
|
@ -98,7 +96,7 @@ add_executable(shadps4
|
||||||
src/Core/PS4/HLE/Kernel/cpu_management.cpp
|
src/Core/PS4/HLE/Kernel/cpu_management.cpp
|
||||||
src/Core/PS4/HLE/Kernel/cpu_management.h
|
src/Core/PS4/HLE/Kernel/cpu_management.h
|
||||||
|
|
||||||
"src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h" "src/Core/PS4/HLE/Graphics/graphics_render.cpp" "src/Core/PS4/HLE/Graphics/graphics_render.h" "src/Core/PS4/GPU/tile_manager.cpp" "src/Core/PS4/GPU/tile_manager.h" "src/version.h" "src/Emulator/HLE/Libraries/LibSystemService/system_service.cpp" "src/Emulator/HLE/Libraries/LibSystemService/system_service.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.cpp")
|
"src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h" "src/Core/PS4/HLE/Graphics/graphics_render.cpp" "src/Core/PS4/HLE/Graphics/graphics_render.h" "src/Core/PS4/GPU/tile_manager.cpp" "src/Core/PS4/GPU/tile_manager.h" "src/version.h" "src/Emulator/HLE/Libraries/LibSystemService/system_service.cpp" "src/Emulator/HLE/Libraries/LibSystemService/system_service.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.cpp")
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools)
|
target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools)
|
||||||
|
|
|
@ -14,7 +14,7 @@ void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
|
||||||
void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) {
|
void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) {
|
||||||
auto* gpumemory = singleton<GPUMemory>::instance();
|
auto* gpumemory = singleton<GPUMemory>::instance();
|
||||||
|
|
||||||
Lib::LockMutexGuard lock(gpumemory->m_mutex);
|
std::scoped_lock lock{gpumemory->m_mutex};
|
||||||
|
|
||||||
MemoryHeap h;
|
MemoryHeap h;
|
||||||
h.allocated_virtual_addr = virtual_addr;
|
h.allocated_virtual_addr = virtual_addr;
|
||||||
|
@ -80,7 +80,7 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
|
||||||
int virtual_addr_num, const GPUObject& info) {
|
int virtual_addr_num, const GPUObject& info) {
|
||||||
auto* gpumemory = singleton<GPUMemory>::instance();
|
auto* gpumemory = singleton<GPUMemory>::instance();
|
||||||
|
|
||||||
Lib::LockMutexGuard lock(gpumemory->m_mutex);
|
std::scoped_lock lock{gpumemory->m_mutex};
|
||||||
|
|
||||||
int heap_id = gpumemory->getHeapId(virtual_addr[0], size[0]);
|
int heap_id = gpumemory->getHeapId(virtual_addr[0], size[0]);
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) {
|
void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
int heap_id = 0;
|
int heap_id = 0;
|
||||||
for (auto& heap : m_heaps) {
|
for (auto& heap : m_heaps) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace GPU {
|
namespace GPU {
|
||||||
|
@ -66,7 +67,7 @@ class GPUMemory {
|
||||||
GPUMemory() {}
|
GPUMemory() {}
|
||||||
virtual ~GPUMemory() {}
|
virtual ~GPUMemory() {}
|
||||||
int getHeapId(u64 vaddr, u64 size);
|
int getHeapId(u64 vaddr, u64 size);
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::vector<MemoryHeap> m_heaps;
|
std::vector<MemoryHeap> m_heaps;
|
||||||
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr,
|
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);
|
const u64* size, int virtual_addr_num, const GPUObject& info);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "tile_manager.h"
|
#include "tile_manager.h"
|
||||||
#include "Lib/Threads.h"
|
|
||||||
#include "Emulator/Util/singleton.h"
|
#include "Emulator/Util/singleton.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace GPU {
|
namespace GPU {
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ class TileManager {
|
||||||
public:
|
public:
|
||||||
TileManager(){}
|
TileManager(){}
|
||||||
virtual ~TileManager() { }
|
virtual ~TileManager() { }
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TileManager32 {
|
class TileManager32 {
|
||||||
|
@ -145,7 +145,7 @@ void convertTileToLinear(void* dst, const void* src,u32 width, u32 height, bool
|
||||||
|
|
||||||
auto* g_TileManager = singleton<TileManager>::instance();
|
auto* g_TileManager = singleton<TileManager>::instance();
|
||||||
|
|
||||||
Lib::LockMutexGuard lock(g_TileManager->m_mutex);
|
std::scoped_lock lock{g_TileManager->m_mutex};
|
||||||
|
|
||||||
for (u32 y = 0; y < height; y++) {
|
for (u32 y = 0; y < height; y++) {
|
||||||
u32 x = 0;
|
u32 x = 0;
|
||||||
|
|
|
@ -12,7 +12,7 @@ void VideoOutCtx::Init(u32 width, u32 height) {
|
||||||
m_video_out_ctx.m_resolution.paneHeight = height;
|
m_video_out_ctx.m_resolution.paneHeight = height;
|
||||||
}
|
}
|
||||||
int VideoOutCtx::Open() {
|
int VideoOutCtx::Open() {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
int handle = -1;
|
int handle = -1;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ int VideoOutCtx::Open() {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
void VideoOutCtx::Close(s32 handle) {
|
void VideoOutCtx::Close(s32 handle) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
m_video_out_ctx.isOpened = false;
|
m_video_out_ctx.isOpened = false;
|
||||||
|
|
||||||
|
@ -55,18 +55,19 @@ void VideoOutCtx::Close(s32 handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
|
VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
|
||||||
if (handle != 1) return nullptr;
|
if (handle != 1) [[unlikely]] {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more
|
return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) {
|
void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
*out = cfg->m_flip_status;
|
*out = cfg->m_flip_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
|
bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
if (m_requests.size() >= 2) {
|
if (m_requests.size() >= 2) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -83,52 +84,53 @@ bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
|
||||||
cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
||||||
cfg->m_flip_status.gcQueueNum = 0;
|
cfg->m_flip_status.gcQueueNum = 0;
|
||||||
|
|
||||||
m_submit_cond.SignalCondVar();
|
m_submit_cond.notify_one();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipQueue::flip(u32 micros) {
|
bool FlipQueue::flip(u32 micros) {
|
||||||
m_mutex.LockMutex();
|
const auto request = [&]() -> Request* {
|
||||||
if (m_requests.size() == 0) {
|
std::unique_lock lock{m_mutex};
|
||||||
m_submit_cond.WaitCondVarFor(&m_mutex, micros);
|
m_submit_cond.wait_for(lock, std::chrono::microseconds(micros),
|
||||||
|
[&] { return !m_requests.empty(); });
|
||||||
if (m_requests.size() == 0) {
|
if (m_requests.empty()) {
|
||||||
m_mutex.UnlockMutex();
|
return nullptr;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return &m_requests.at(0); // Process first request
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
auto request = m_requests.at(0); // proceed first request
|
|
||||||
m_mutex.UnlockMutex();
|
|
||||||
|
|
||||||
auto* buffer = request.cfg->buffers[request.index].buffer_render;
|
|
||||||
|
|
||||||
|
const auto buffer = request->cfg->buffers[request->index].buffer_render;
|
||||||
Emu::DrawBuffer(buffer);
|
Emu::DrawBuffer(buffer);
|
||||||
|
|
||||||
m_mutex.LockMutex();
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
request.cfg->m_mutex.LockMutex();
|
{
|
||||||
for (auto& flip_eq : request.cfg->m_flip_evtEq) {
|
std::scoped_lock cfg_lock{request->cfg->m_mutex};
|
||||||
if (flip_eq != nullptr) {
|
for (auto& flip_eq : request->cfg->m_flip_evtEq) {
|
||||||
flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, HLE::Kernel::Objects::EVFILT_VIDEO_OUT, reinterpret_cast<void*>(request.flip_arg));
|
if (flip_eq != nullptr) {
|
||||||
|
flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, HLE::Kernel::Objects::EVFILT_VIDEO_OUT,
|
||||||
|
reinterpret_cast<void*>(request->flip_arg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request.cfg->m_mutex.UnlockMutex();
|
|
||||||
|
|
||||||
m_requests.erase(m_requests.begin());
|
m_requests.erase(m_requests.begin());
|
||||||
m_done_cond.SignalCondVar();
|
m_done_cond.notify_one();
|
||||||
|
|
||||||
request.cfg->m_flip_status.count++;
|
request->cfg->m_flip_status.count++;
|
||||||
//TODO request.cfg->m_flip_status.processTime = LibKernel::KernelGetProcessTime();
|
//TODO request.cfg->m_flip_status.processTime = LibKernel::KernelGetProcessTime();
|
||||||
request.cfg->m_flip_status.tsc = HLE::Libs::LibKernel::sceKernelReadTsc();
|
request->cfg->m_flip_status.tsc = HLE::Libs::LibKernel::sceKernelReadTsc();
|
||||||
request.cfg->m_flip_status.submitTsc = request.submit_tsc;
|
request->cfg->m_flip_status.submitTsc = request->submit_tsc;
|
||||||
request.cfg->m_flip_status.flipArg = request.flip_arg;
|
request->cfg->m_flip_status.flipArg = request->flip_arg;
|
||||||
request.cfg->m_flip_status.currentBuffer = request.index;
|
request->cfg->m_flip_status.currentBuffer = request->index;
|
||||||
request.cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
request->cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
||||||
|
|
||||||
m_mutex.UnlockMutex();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace HLE::Graphics::Objects
|
}; // namespace HLE::Graphics::Objects
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
#include <Core/PS4/HLE/Graphics/video_out.h>
|
#include <Core/PS4/HLE/Graphics/video_out.h>
|
||||||
#include <Lib/Threads.h>
|
|
||||||
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
||||||
#include <emulator.h>
|
#include <emulator.h>
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ struct VideoOutBufferInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoConfigInternal {
|
struct VideoConfigInternal {
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
SceVideoOutResolutionStatus m_resolution;
|
SceVideoOutResolutionStatus m_resolution;
|
||||||
bool isOpened = false;
|
bool isOpened = false;
|
||||||
SceVideoOutFlipStatus m_flip_status;
|
SceVideoOutFlipStatus m_flip_status;
|
||||||
|
@ -45,9 +47,9 @@ class FlipQueue {
|
||||||
uint64_t submit_tsc;
|
uint64_t submit_tsc;
|
||||||
};
|
};
|
||||||
|
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
Lib::ConditionVariable m_submit_cond;
|
std::condition_variable m_submit_cond;
|
||||||
Lib::ConditionVariable m_done_cond;
|
std::condition_variable m_done_cond;
|
||||||
std::vector<Request> m_requests;
|
std::vector<Request> m_requests;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,16 +64,16 @@ class VideoOutCtx {
|
||||||
VideoConfigInternal* getCtx(int handle);
|
VideoConfigInternal* getCtx(int handle);
|
||||||
FlipQueue& getFlipQueue() { return m_flip_queue; }
|
FlipQueue& getFlipQueue() { return m_flip_queue; }
|
||||||
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
|
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
if (m_graphic_ctx == nullptr) {
|
if (!m_graphic_ctx) {
|
||||||
m_graphic_ctx = Emu::getGraphicCtx();
|
m_graphic_ctx = Emu::getGraphicCtx();
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_graphic_ctx;
|
return m_graphic_ctx;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
VideoConfigInternal m_video_out_ctx;
|
VideoConfigInternal m_video_out_ctx;
|
||||||
FlipQueue m_flip_queue;
|
FlipQueue m_flip_queue;
|
||||||
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
|
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include <mutex>
|
||||||
#include "Lib/Threads.h"
|
|
||||||
|
|
||||||
namespace HLE::Libs::Graphics {
|
namespace HLE::Libs::Graphics {
|
||||||
|
|
||||||
struct VulkanCommandPool {
|
struct VulkanCommandPool {
|
||||||
Lib::Mutex mutex;
|
std::mutex mutex;
|
||||||
VkCommandPool pool = nullptr;
|
VkCommandPool pool = nullptr;
|
||||||
VkCommandBuffer* buffers = nullptr;
|
VkCommandBuffer* buffers = nullptr;
|
||||||
VkFence* fences = nullptr;
|
VkFence* fences = nullptr;
|
||||||
|
@ -18,7 +17,7 @@ struct VulkanCommandPool {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VulkanQueueInfo {
|
struct VulkanQueueInfo {
|
||||||
Lib::Mutex* mutex = nullptr;
|
std::mutex* mutex = nullptr;
|
||||||
u32 family = static_cast<u32>(-1);
|
u32 family = static_cast<u32>(-1);
|
||||||
u32 index = static_cast<u32>(-1);
|
u32 index = static_cast<u32>(-1);
|
||||||
VkQueue vk_queue = nullptr;
|
VkQueue vk_queue = nullptr;
|
||||||
|
|
|
@ -14,7 +14,7 @@ void GPU::renderCreateCtx() {
|
||||||
void GPU::CommandBuffer::allocateBuffer() {
|
void GPU::CommandBuffer::allocateBuffer() {
|
||||||
m_pool = g_command_pool.getPool(m_queue);
|
m_pool = g_command_pool.getPool(m_queue);
|
||||||
|
|
||||||
Lib::LockMutexGuard lock(m_pool->mutex);
|
std::scoped_lock lock{m_pool->mutex};
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
|
for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
|
||||||
if (!m_pool->busy[i]) {
|
if (!m_pool->busy[i]) {
|
||||||
|
@ -27,7 +27,7 @@ void GPU::CommandBuffer::allocateBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::CommandBuffer::freeBuffer() {
|
void GPU::CommandBuffer::freeBuffer() {
|
||||||
Lib::LockMutexGuard lock(m_pool->mutex);
|
std::scoped_lock lock{m_pool->mutex};
|
||||||
|
|
||||||
waitForFence();
|
waitForFence();
|
||||||
|
|
||||||
|
@ -91,17 +91,8 @@ void GPU::CommandBuffer::executeWithSemaphore() {
|
||||||
|
|
||||||
auto* render_ctx = singleton<RenderCtx>::instance();
|
auto* render_ctx = singleton<RenderCtx>::instance();
|
||||||
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
|
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
|
||||||
|
|
||||||
if (queue.mutex != nullptr) {
|
|
||||||
queue.mutex->LockMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
|
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
|
||||||
|
|
||||||
if (queue.mutex != nullptr) {
|
|
||||||
queue.mutex->LockMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_execute = true;
|
m_execute = true;
|
||||||
|
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
@ -126,17 +117,8 @@ void GPU::CommandBuffer::execute() {
|
||||||
|
|
||||||
auto* render_ctx = singleton<RenderCtx>::instance();
|
auto* render_ctx = singleton<RenderCtx>::instance();
|
||||||
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
|
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
|
||||||
|
|
||||||
if (queue.mutex != nullptr) {
|
|
||||||
queue.mutex->LockMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
|
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
|
||||||
|
|
||||||
if (queue.mutex != nullptr) {
|
|
||||||
queue.mutex->UnlockMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_execute = true;
|
m_execute = true;
|
||||||
|
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue
|
||||||
if (ctx == nullptr) {
|
if (ctx == nullptr) {
|
||||||
return SCE_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
return SCE_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
Lib::LockMutexGuard lock(ctx->m_mutex);
|
std::scoped_lock lock(ctx->m_mutex);
|
||||||
|
|
||||||
if (eq == nullptr) {
|
if (eq == nullptr) {
|
||||||
return SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE;
|
return SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE;
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#include "event_queue.h"
|
#include "event_queue.h"
|
||||||
|
|
||||||
#include <Lib/Timer.h>
|
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
namespace HLE::Kernel::Objects {
|
namespace HLE::Kernel::Objects {
|
||||||
EqueueInternal::~EqueueInternal() {}
|
EqueueInternal::~EqueueInternal() {}
|
||||||
|
|
||||||
int EqueueInternal::addEvent(const EqueueEvent& event) {
|
int EqueueInternal::addEvent(const EqueueEvent& event) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
if (m_events.size() > 0) {
|
if (m_events.size() > 0) {
|
||||||
BREAKPOINT();
|
BREAKPOINT();
|
||||||
|
@ -24,11 +23,10 @@ int EqueueInternal::addEvent(const EqueueEvent& event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::unique_lock lock{m_mutex};
|
||||||
|
|
||||||
u32 timeElapsed = 0;
|
u64 timeElapsed = 0;
|
||||||
Lib::Timer t;
|
const auto start = std::chrono::high_resolution_clock::now();
|
||||||
t.Start();
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = getTriggeredEvents(ev, num);
|
int ret = getTriggeredEvents(ev, num);
|
||||||
|
@ -38,19 +36,20 @@ int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (micros == 0) {
|
if (micros == 0) {
|
||||||
m_cond.WaitCondVar(&m_mutex);
|
m_cond.wait(lock);
|
||||||
} else {
|
} else {
|
||||||
m_cond.WaitCondVarFor(&m_mutex, micros - timeElapsed);
|
m_cond.wait_for(lock, std::chrono::microseconds(micros - timeElapsed));
|
||||||
}
|
}
|
||||||
|
|
||||||
timeElapsed = static_cast<uint32_t>(t.GetTimeSec() * 1000000.0);
|
const auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
timeElapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
if (m_events.size() > 1) {
|
if (m_events.size() > 1) {
|
||||||
BREAKPOINT(); // we currently support one event
|
BREAKPOINT(); // we currently support one event
|
||||||
|
@ -63,14 +62,12 @@ bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
||||||
event.isTriggered = true;
|
event.isTriggered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cond.SignalCondVar();
|
m_cond.notify_one();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) {
|
int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (m_events.size() > 1) {
|
if (m_events.size() > 1) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <Lib/Threads.h>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -71,8 +72,8 @@ class EqueueInternal {
|
||||||
int getTriggeredEvents(SceKernelEvent* ev, int num);
|
int getTriggeredEvents(SceKernelEvent* ev, int num);
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::vector<EqueueEvent> m_events;
|
std::vector<EqueueEvent> m_events;
|
||||||
Lib::ConditionVariable m_cond;
|
std::condition_variable m_cond;
|
||||||
};
|
};
|
||||||
}; // namespace HLE::Kernel::Objects
|
}; // namespace HLE::Kernel::Objects
|
|
@ -5,7 +5,7 @@ namespace HLE::Kernel::Objects {
|
||||||
static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); }
|
static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); }
|
||||||
|
|
||||||
bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType) {
|
bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
u64 find_free_pos = 0;
|
u64 find_free_pos = 0;
|
||||||
|
|
||||||
// iterate through allocated blocked and find the next free position
|
// iterate through allocated blocked and find the next free position
|
||||||
|
@ -40,7 +40,7 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode) {
|
bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
for (auto& b : m_allocatedBlocks) {
|
for (auto& b : m_allocatedBlocks) {
|
||||||
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) {
|
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) {
|
||||||
if (b.map_virtual_addr != 0 || b.map_size != 0) {
|
if (b.map_virtual_addr != 0 || b.map_size != 0) {
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <Core/virtual_memory.h>
|
#include <Core/virtual_memory.h>
|
||||||
#include <Core/PS4/GPU/gpu_memory.h>
|
#include <Core/PS4/GPU/gpu_memory.h>
|
||||||
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Lib/Threads.h"
|
|
||||||
|
|
||||||
namespace HLE::Kernel::Objects {
|
namespace HLE::Kernel::Objects {
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class PhysicalMemory {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<AllocatedBlock> m_allocatedBlocks;
|
std::vector<AllocatedBlock> m_allocatedBlocks;
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HLE::Kernel::Objects
|
} // namespace HLE::Kernel::Objects
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <Util/log.h>
|
#include <Util/log.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#include "Emulator/Util/singleton.h"
|
#include "Emulator/Util/singleton.h"
|
||||||
#include "../Loader/Elf.h"
|
#include "../Loader/Elf.h"
|
||||||
|
|
|
@ -70,7 +70,7 @@ static std::string encodeId(u64 nVal)
|
||||||
}
|
}
|
||||||
Module* Linker::LoadModule(const std::string& elf_name)
|
Module* Linker::LoadModule(const std::string& elf_name)
|
||||||
{
|
{
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
auto* m = new Module;
|
auto* m = new Module;
|
||||||
m->linker = this;
|
m->linker = this;
|
||||||
m->elf = new Elf;
|
m->elf = new Elf;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
#include "Loader/Elf.h"
|
#include "Loader/Elf.h"
|
||||||
#include "Loader/SymbolsResolver.h"
|
#include "Loader/SymbolsResolver.h"
|
||||||
#include "Lib/Threads.h"
|
|
||||||
|
|
||||||
struct DynamicModuleInfo;
|
struct DynamicModuleInfo;
|
||||||
class Linker;
|
class Linker;
|
||||||
|
@ -130,5 +130,5 @@ public:
|
||||||
|
|
||||||
std::vector<Module*> m_modules;
|
std::vector<Module*> m_modules;
|
||||||
SymbolsResolver* m_HLEsymbols = nullptr;
|
SymbolsResolver* m_HLEsymbols = nullptr;
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
|
@ -5,7 +5,7 @@ GameController::GameController() { m_states_num = 0;
|
||||||
m_last_state = State();
|
m_last_state = State();
|
||||||
}
|
}
|
||||||
void GameController::readState(State* state, bool* isConnected, int* connectedCount) {
|
void GameController::readState(State* state, bool* isConnected, int* connectedCount) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
*isConnected = m_connected;
|
*isConnected = m_connected;
|
||||||
*connectedCount = m_connected_count;
|
*connectedCount = m_connected_count;
|
||||||
|
@ -37,7 +37,7 @@ void GameController::addState(const State& state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::checKButton(int id, u32 button, bool isPressed) {
|
void GameController::checKButton(int id, u32 button, bool isPressed) {
|
||||||
Lib::LockMutexGuard lock(m_mutex);
|
std::scoped_lock lock{m_mutex};
|
||||||
auto state = getLastState();
|
auto state = getLastState();
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
state.buttonsState |= button;
|
state.buttonsState |= button;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include "Lib/Threads.h"
|
#include <mutex>
|
||||||
|
|
||||||
namespace Emulator::Host::Controller {
|
namespace Emulator::Host::Controller {
|
||||||
struct State {
|
struct State {
|
||||||
|
@ -21,7 +21,7 @@ class GameController {
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
bool m_connected = false;
|
bool m_connected = false;
|
||||||
State m_last_state;
|
State m_last_state;
|
||||||
int m_connected_count = 0;
|
int m_connected_count = 0;
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
#include "Threads.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
static std::thread::id g_main_thread;
|
|
||||||
static int g_main_thread_int;
|
|
||||||
static std::atomic<int> g_thread_counter = 0;
|
|
||||||
|
|
||||||
void Lib::InitThreads() {
|
|
||||||
g_main_thread = std::this_thread::get_id();
|
|
||||||
g_main_thread_int = Lib::Thread::GetThreadIdUnique();
|
|
||||||
}
|
|
||||||
|
|
||||||
Lib::Thread::Thread(thread_func_t func, void* arg) {
|
|
||||||
m_thread = new ThreadStructInternal(func, arg);
|
|
||||||
while (!m_thread->started) {
|
|
||||||
SleepThreadMicro(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Lib::Thread::~Thread() { delete m_thread; }
|
|
||||||
|
|
||||||
void Lib::Thread::JoinThread() { m_thread->m_thread.join(); }
|
|
||||||
|
|
||||||
void Lib::Thread::DetachThread() { m_thread->m_thread.detach(); }
|
|
||||||
|
|
||||||
std::string Lib::Thread::GetId() const {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << m_thread->m_thread.get_id();
|
|
||||||
return ss.str().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Lib::Thread::GetUniqueId() const { return m_thread->unique_id; }
|
|
||||||
|
|
||||||
void Lib::Thread::SleepThread(u32 millis) { std::this_thread::sleep_for(std::chrono::milliseconds(millis)); }
|
|
||||||
|
|
||||||
void Lib::Thread::SleepThreadMicro(u32 micros) { std::this_thread::sleep_for(std::chrono::microseconds(micros)); }
|
|
||||||
|
|
||||||
void Lib::Thread::SleepThreadNano(u64 nanos) { std::this_thread::sleep_for(std::chrono::nanoseconds(nanos)); }
|
|
||||||
|
|
||||||
bool Lib::Thread::IsMainThread() { return g_main_thread == std::this_thread::get_id(); }
|
|
||||||
|
|
||||||
std::string Lib::Thread::GetThreadId() {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::this_thread::get_id();
|
|
||||||
return ss.str().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Lib::Thread::GetThreadIdUnique() {
|
|
||||||
static thread_local int tid = ++g_thread_counter;
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lib::Mutex::Mutex() { m_mutex = new MutexStructInternal(); }
|
|
||||||
|
|
||||||
Lib::Mutex::~Mutex() { delete m_mutex; }
|
|
||||||
|
|
||||||
void Lib::Mutex::LockMutex() { EnterCriticalSection(&m_mutex->m_cs); }
|
|
||||||
|
|
||||||
void Lib::Mutex::UnlockMutex() { LeaveCriticalSection(&m_mutex->m_cs); }
|
|
||||||
|
|
||||||
bool Lib::Mutex::TryLockMutex() { return (TryEnterCriticalSection(&m_mutex->m_cs) != 0); }
|
|
||||||
|
|
||||||
Lib::ConditionVariable::ConditionVariable() { m_cond_var = new ConditionVariableStructInternal(); }
|
|
||||||
|
|
||||||
Lib::ConditionVariable::~ConditionVariable() { delete m_cond_var; }
|
|
||||||
|
|
||||||
void Lib::ConditionVariable::WaitCondVar(Mutex* mutex) { SleepConditionVariableCS(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, INFINITE); }
|
|
||||||
|
|
||||||
bool Lib::ConditionVariable::WaitCondVarFor(Mutex* mutex, u32 micros) {
|
|
||||||
bool ok = false;
|
|
||||||
ok = !(SleepConditionVariableCS(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, (micros < 1000 ? 1 : micros / 1000)) == 0 &&
|
|
||||||
GetLastError() == ERROR_TIMEOUT);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lib::ConditionVariable::SignalCondVar() { WakeConditionVariable(&m_cond_var->m_cv); }
|
|
||||||
|
|
||||||
void Lib::ConditionVariable::SignalCondVarAll() { WakeAllConditionVariable(&m_cond_var->m_cv); }
|
|
|
@ -1,131 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "windows.h"
|
|
||||||
#include <synchapi.h>
|
|
||||||
#include <atomic>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <string>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "../types.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Lib {
|
|
||||||
using thread_func_t = void (*)(void*);
|
|
||||||
|
|
||||||
void InitThreads();
|
|
||||||
|
|
||||||
struct ThreadStructInternal;
|
|
||||||
struct MutexStructInternal;
|
|
||||||
struct ConditionVariableStructInternal;
|
|
||||||
|
|
||||||
class Thread {
|
|
||||||
public:
|
|
||||||
Thread(thread_func_t func, void* arg);
|
|
||||||
virtual ~Thread();
|
|
||||||
|
|
||||||
void JoinThread();
|
|
||||||
void DetachThread();
|
|
||||||
|
|
||||||
std::string GetId() const;
|
|
||||||
int GetUniqueId() const;
|
|
||||||
|
|
||||||
static void SleepThread(u32 millis);
|
|
||||||
static void SleepThreadMicro(u32 micros);
|
|
||||||
static void SleepThreadNano(u64 nanos);
|
|
||||||
static bool IsMainThread();
|
|
||||||
|
|
||||||
// Get current thread id (reusable id)
|
|
||||||
static std::string GetThreadId();
|
|
||||||
|
|
||||||
// Get current thread id (unique id)
|
|
||||||
static int GetThreadIdUnique();
|
|
||||||
|
|
||||||
public:
|
|
||||||
Thread(const Thread&) = delete;
|
|
||||||
Thread& operator=(const Thread&) = delete;
|
|
||||||
Thread(Thread&&) = delete;
|
|
||||||
Thread& operator=(Thread&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ThreadStructInternal* m_thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ThreadStructInternal {
|
|
||||||
ThreadStructInternal(thread_func_t f, void* a) : func(f), arg(a), m_thread(&Run, this) {}
|
|
||||||
|
|
||||||
static void Run(ThreadStructInternal* t) {
|
|
||||||
t->unique_id = Lib::Thread::GetThreadIdUnique();
|
|
||||||
t->started = true;
|
|
||||||
t->func(t->arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_func_t func;
|
|
||||||
void* arg;
|
|
||||||
std::atomic_bool started = false;
|
|
||||||
int unique_id = 0;
|
|
||||||
std::thread m_thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Mutex {
|
|
||||||
public:
|
|
||||||
Mutex();
|
|
||||||
virtual ~Mutex();
|
|
||||||
|
|
||||||
void LockMutex();
|
|
||||||
void UnlockMutex();
|
|
||||||
bool TryLockMutex();
|
|
||||||
|
|
||||||
friend class ConditionVariable;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Mutex(const Mutex&) = delete;
|
|
||||||
Mutex& operator=(const Mutex&) = delete;
|
|
||||||
Mutex(Mutex&&) = delete;
|
|
||||||
Mutex& operator=(Mutex&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MutexStructInternal* m_mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MutexStructInternal {
|
|
||||||
MutexStructInternal() { InitializeCriticalSectionAndSpinCount(&m_cs, 4000); }
|
|
||||||
~MutexStructInternal() { DeleteCriticalSection(&m_cs); }
|
|
||||||
CRITICAL_SECTION m_cs{};
|
|
||||||
};
|
|
||||||
class ConditionVariable {
|
|
||||||
public:
|
|
||||||
ConditionVariable();
|
|
||||||
virtual ~ConditionVariable();
|
|
||||||
|
|
||||||
void WaitCondVar(Mutex* mutex);
|
|
||||||
bool WaitCondVarFor(Mutex* mutex, u32 micros);
|
|
||||||
void SignalCondVar();
|
|
||||||
void SignalCondVarAll();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ConditionVariableStructInternal* m_cond_var;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ConditionVariableStructInternal {
|
|
||||||
ConditionVariableStructInternal() { InitializeConditionVariable(&m_cv); }
|
|
||||||
~ConditionVariableStructInternal() = default;
|
|
||||||
CONDITION_VARIABLE m_cv{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class LockMutexGuard {
|
|
||||||
public:
|
|
||||||
explicit LockMutexGuard(Mutex& m) : m_mutex(m) { m_mutex.LockMutex(); }
|
|
||||||
|
|
||||||
~LockMutexGuard() { m_mutex.UnlockMutex(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Mutex& m_mutex;
|
|
||||||
|
|
||||||
public:
|
|
||||||
LockMutexGuard(const LockMutexGuard&) = delete;
|
|
||||||
LockMutexGuard& operator=(const LockMutexGuard&) = delete;
|
|
||||||
LockMutexGuard(LockMutexGuard&&) noexcept = delete;
|
|
||||||
LockMutexGuard& operator=(LockMutexGuard&&) noexcept = delete;
|
|
||||||
};
|
|
||||||
} // namespace Lib
|
|
|
@ -1,103 +0,0 @@
|
||||||
#include "Timer.h"
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Lib::Timer::Timer() {
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER f;
|
|
||||||
QueryPerformanceFrequency(&f);
|
|
||||||
m_Frequency = f.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer constructor
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lib::Timer::Start() {
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
m_StartTime = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::Start()
|
|
||||||
#endif
|
|
||||||
m_is_timer_paused = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lib::Timer::Pause() {
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
m_PauseTime = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::Pause()
|
|
||||||
#endif
|
|
||||||
m_is_timer_paused = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lib::Timer::Resume() {
|
|
||||||
u64 current_time = 0;
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
current_time = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::Resume()
|
|
||||||
#endif
|
|
||||||
m_StartTime += current_time - m_PauseTime;
|
|
||||||
m_is_timer_paused = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Lib::Timer::IsPaused() const { return m_is_timer_paused; }
|
|
||||||
|
|
||||||
double Lib::Timer::GetTimeMsec() const {
|
|
||||||
if (m_is_timer_paused) {
|
|
||||||
return 1000.0 * (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 current_time = 0;
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
current_time = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::GetTimeMsec()
|
|
||||||
#endif
|
|
||||||
return 1000.0 * (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Lib::Timer::GetTimeSec() const {
|
|
||||||
if (m_is_timer_paused) {
|
|
||||||
return (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 current_time = 0;
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
current_time = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::GetTimeSec()
|
|
||||||
#endif
|
|
||||||
return (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 Lib::Timer::GetTicks() const {
|
|
||||||
if (m_is_timer_paused) {
|
|
||||||
return (m_PauseTime - m_StartTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 current_time = 0;
|
|
||||||
#ifdef _WIN64
|
|
||||||
LARGE_INTEGER c;
|
|
||||||
QueryPerformanceCounter(&c);
|
|
||||||
current_time = c.QuadPart;
|
|
||||||
#else
|
|
||||||
#error Unimplemented Timer::GetTicks()
|
|
||||||
#endif
|
|
||||||
return (current_time - m_StartTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 Lib::Timer::GetFrequency() const { return m_Frequency; }
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../types.h"
|
|
||||||
|
|
||||||
namespace Lib {
|
|
||||||
class Timer final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Timer();
|
|
||||||
~Timer() = default;
|
|
||||||
|
|
||||||
void Start();
|
|
||||||
void Pause();
|
|
||||||
void Resume();
|
|
||||||
bool IsPaused() const;
|
|
||||||
|
|
||||||
double GetTimeMsec() const;// return time in milliseconds
|
|
||||||
double GetTimeSec() const;// return time in seconds
|
|
||||||
u64 GetTicks() const;// return time in ticks
|
|
||||||
u64 GetFrequency() const;// return ticks frequency
|
|
||||||
|
|
||||||
public:
|
|
||||||
Timer(const Timer&) = delete;
|
|
||||||
Timer& operator=(const Timer&) = delete;
|
|
||||||
Timer(Timer&&) = delete;
|
|
||||||
Timer& operator=(Timer&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_is_timer_paused = true;
|
|
||||||
u64 m_Frequency = 0;
|
|
||||||
u64 m_StartTime = 0;
|
|
||||||
u64 m_PauseTime = 0;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -22,10 +22,10 @@ void emuInit(u32 width, u32 height) {
|
||||||
|
|
||||||
void checkAndWaitForGraphicsInit() {
|
void checkAndWaitForGraphicsInit() {
|
||||||
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
||||||
Lib::LockMutexGuard lock(window_ctx->m_mutex);
|
std::unique_lock lock{window_ctx->m_mutex};
|
||||||
|
|
||||||
while (!window_ctx->m_is_graphic_initialized) {
|
while (!window_ctx->m_is_graphic_initialized) {
|
||||||
window_ctx->m_graphic_initialized_cond.WaitCondVar(&window_ctx->m_mutex);
|
window_ctx->m_graphic_initialized_cond.wait(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void CreateSdlWindow(WindowCtx* ctx) {
|
static void CreateSdlWindow(WindowCtx* ctx) {
|
||||||
|
@ -51,15 +51,14 @@ static void CreateSdlWindow(WindowCtx* ctx) {
|
||||||
}
|
}
|
||||||
void emuRun() {
|
void emuRun() {
|
||||||
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
||||||
window_ctx->m_mutex.LockMutex();
|
|
||||||
{
|
{
|
||||||
// init window and wait until init finishes
|
// init window and wait until init finishes
|
||||||
|
std::scoped_lock lock{window_ctx->m_mutex};
|
||||||
CreateSdlWindow(window_ctx);
|
CreateSdlWindow(window_ctx);
|
||||||
Graphics::Vulkan::vulkanCreate(window_ctx);
|
Graphics::Vulkan::vulkanCreate(window_ctx);
|
||||||
window_ctx->m_is_graphic_initialized = true;
|
window_ctx->m_is_graphic_initialized = true;
|
||||||
window_ctx->m_graphic_initialized_cond.SignalCondVar();
|
window_ctx->m_graphic_initialized_cond.notify_one();
|
||||||
}
|
}
|
||||||
window_ctx->m_mutex.UnlockMutex();
|
|
||||||
|
|
||||||
bool exit_loop = false;
|
bool exit_loop = false;
|
||||||
|
|
||||||
|
@ -99,8 +98,7 @@ void emuRun() {
|
||||||
|
|
||||||
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
|
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
|
||||||
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
||||||
Lib::LockMutexGuard lock(window_ctx->m_mutex);
|
std::scoped_lock lock{window_ctx->m_mutex};
|
||||||
|
|
||||||
return &window_ctx->m_graphic_ctx;
|
return &window_ctx->m_graphic_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
#include <Core/PS4/HLE/Graphics/graphics_ctx.h>
|
||||||
#include <Lib/Threads.h>
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Emu {
|
namespace Emu {
|
||||||
|
@ -57,9 +59,9 @@ struct VulkanSwapchain {
|
||||||
|
|
||||||
struct WindowCtx {
|
struct WindowCtx {
|
||||||
HLE::Libs::Graphics::GraphicCtx m_graphic_ctx;
|
HLE::Libs::Graphics::GraphicCtx m_graphic_ctx;
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
bool m_is_graphic_initialized = false;
|
bool m_is_graphic_initialized = false;
|
||||||
Lib::ConditionVariable m_graphic_initialized_cond;
|
std::condition_variable m_graphic_initialized_cond;
|
||||||
SDL_Window* m_window = nullptr;
|
SDL_Window* m_window = nullptr;
|
||||||
bool is_window_hidden = true;
|
bool is_window_hidden = true;
|
||||||
VkSurfaceKHR m_surface = nullptr;
|
VkSurfaceKHR m_surface = nullptr;
|
||||||
|
@ -69,7 +71,7 @@ struct WindowCtx {
|
||||||
|
|
||||||
struct EmuPrivate {
|
struct EmuPrivate {
|
||||||
EmuPrivate() = default;
|
EmuPrivate() = default;
|
||||||
Lib::Mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
|
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
|
||||||
void* data1 = nullptr;
|
void* data1 = nullptr;
|
||||||
void* data2 = nullptr;
|
void* data2 = nullptr;
|
||||||
|
|
|
@ -31,10 +31,10 @@
|
||||||
#include <emulator.h>
|
#include <emulator.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "Core/PS4/HLE/Libs.h"
|
#include "Core/PS4/HLE/Libs.h"
|
||||||
#include "Core/PS4/Linker.h"
|
#include "Core/PS4/Linker.h"
|
||||||
#include "Lib/Threads.h"
|
|
||||||
#include "Emulator/Util\singleton.h"
|
#include "Emulator/Util\singleton.h"
|
||||||
#include "discord.h"
|
#include "discord.h"
|
||||||
|
|
||||||
|
@ -50,25 +50,22 @@ int main(int argc, char* argv[]) {
|
||||||
auto height = Config::getScreenHeight();
|
auto height = Config::getScreenHeight();
|
||||||
Emu::emuInit(width, height);
|
Emu::emuInit(width, height);
|
||||||
HLE::Libs::Graphics::VideoOut::videoOutInit(width, height);
|
HLE::Libs::Graphics::VideoOut::videoOutInit(width, height);
|
||||||
Lib::InitThreads();
|
|
||||||
|
|
||||||
const char* const path = argv[1]; // argument 1 is the path of self file to boot
|
const char* const path = argv[1]; // argument 1 is the path of self file to boot
|
||||||
|
|
||||||
auto* linker = singleton<Linker>::instance();
|
auto* linker = singleton<Linker>::instance();
|
||||||
HLE::Libs::Init_HLE_Libs(linker->getHLESymbols());
|
HLE::Libs::Init_HLE_Libs(linker->getHLESymbols());
|
||||||
auto* module = linker->LoadModule(path); // load main executable
|
auto* module = linker->LoadModule(path); // load main executable
|
||||||
Lib::Thread mainthread(
|
std::jthread mainthread(
|
||||||
[](void*) {
|
[](std::stop_token stop_token, void*) {
|
||||||
auto* linker = singleton<Linker>::instance();
|
auto* linker = singleton<Linker>::instance();
|
||||||
linker->Execute();
|
linker->Execute();
|
||||||
},
|
},
|
||||||
nullptr);
|
nullptr);
|
||||||
mainthread.DetachThread();
|
|
||||||
Discord::RPC discordRPC;
|
Discord::RPC discordRPC;
|
||||||
discordRPC.init();
|
discordRPC.init();
|
||||||
discordRPC.update(Discord::RPCStatus::Idling, "");
|
discordRPC.update(Discord::RPCStatus::Idling, "");
|
||||||
Emu::emuRun();
|
Emu::emuRun();
|
||||||
mainthread.JoinThread();
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Setup SDL
|
// Setup SDL
|
||||||
|
|
|
@ -81,8 +81,6 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) {
|
||||||
|
|
||||||
Emu::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) {
|
Emu::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) {
|
||||||
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
auto* window_ctx = singleton<Emu::WindowCtx>::instance();
|
||||||
Lib::LockMutexGuard lock(window_ctx->m_mutex);
|
|
||||||
|
|
||||||
auto* s = new Emu::VulkanSwapchain;
|
auto* s = new Emu::VulkanSwapchain;
|
||||||
|
|
||||||
VkExtent2D extent{};
|
VkExtent2D extent{};
|
||||||
|
@ -189,7 +187,7 @@ void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx,
|
||||||
ctx->queues[id].index = info.index;
|
ctx->queues[id].index = info.index;
|
||||||
vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue);
|
vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue);
|
||||||
if (with_mutex) {
|
if (with_mutex) {
|
||||||
ctx->queues[id].mutex = new Lib::Mutex;
|
ctx->queues[id].mutex = new std::mutex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue