mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-16 12:09:07 +00:00
Merge branch 'main' into implement-http-uri-escape-unescape
This commit is contained in:
commit
6f500631b9
@ -6,8 +6,8 @@
|
|||||||
#include "common/elf_info.h"
|
#include "common/elf_info.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/fiber/fiber_error.h"
|
#include "core/libraries/fiber/fiber_error.h"
|
||||||
#include "core/libraries/kernel/threads/pthread.h"
|
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
|
#include "core/tls.h"
|
||||||
|
|
||||||
namespace Libraries::Fiber {
|
namespace Libraries::Fiber {
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ static constexpr u64 kFiberStackSizeCheck = 0xdeadbeefdeadbeef;
|
|||||||
static std::atomic<u32> context_size_check = false;
|
static std::atomic<u32> context_size_check = false;
|
||||||
|
|
||||||
OrbisFiberContext* GetFiberContext() {
|
OrbisFiberContext* GetFiberContext() {
|
||||||
return Libraries::Kernel::g_curthread->tcb->tcb_fiber;
|
return Core::GetTcbBase()->tcb_fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" s32 PS4_SYSV_ABI _sceFiberSetJmp(OrbisFiberContext* ctx) asm("_sceFiberSetJmp");
|
extern "C" s32 PS4_SYSV_ABI _sceFiberSetJmp(OrbisFiberContext* ctx) asm("_sceFiberSetJmp");
|
||||||
@ -269,7 +269,7 @@ s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size
|
|||||||
return ORBIS_FIBER_ERROR_INVALID;
|
return ORBIS_FIBER_ERROR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Tcb* tcb = Libraries::Kernel::g_curthread->tcb;
|
Core::Tcb* tcb = Core::GetTcbBase();
|
||||||
if (tcb->tcb_fiber) {
|
if (tcb->tcb_fiber) {
|
||||||
return ORBIS_FIBER_ERROR_PERMISSION;
|
return ORBIS_FIBER_ERROR_PERMISSION;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -663,6 +663,10 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", posix_pthread_once);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", posix_pthread_self);
|
||||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", posix_pthread_create);
|
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", posix_pthread_create);
|
||||||
|
LIB_FUNCTION("lZzFeSxPl08", "libkernel", 1, "libkernel", posix_pthread_setcancelstate);
|
||||||
|
LIB_FUNCTION("CBNtXOoef-E", "libkernel", 1, "libkernel", posix_sched_get_priority_max);
|
||||||
|
LIB_FUNCTION("m0iS6jNsXds", "libkernel", 1, "libkernel", posix_sched_get_priority_min);
|
||||||
|
LIB_FUNCTION("Xs9hdiD7sAA", "libkernel", 1, "libkernel", posix_pthread_setschedparam);
|
||||||
LIB_FUNCTION("+U1R4WtXvoc", "libkernel", 1, "libkernel", posix_pthread_detach);
|
LIB_FUNCTION("+U1R4WtXvoc", "libkernel", 1, "libkernel", posix_pthread_detach);
|
||||||
LIB_FUNCTION("7Xl257M4VNI", "libkernel", 1, "libkernel", posix_pthread_equal);
|
LIB_FUNCTION("7Xl257M4VNI", "libkernel", 1, "libkernel", posix_pthread_equal);
|
||||||
LIB_FUNCTION("h9CcP3J0oVM", "libkernel", 1, "libkernel", posix_pthread_join);
|
LIB_FUNCTION("h9CcP3J0oVM", "libkernel", 1, "libkernel", posix_pthread_join);
|
||||||
|
|||||||
@ -368,7 +368,7 @@ bool Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Modul
|
|||||||
void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
|
|
||||||
DtvEntry* dtv_table = Libraries::Kernel::g_curthread->tcb->tcb_dtv;
|
DtvEntry* dtv_table = GetTcbBase()->tcb_dtv;
|
||||||
if (dtv_table[0].counter != dtv_generation_counter) {
|
if (dtv_table[0].counter != dtv_generation_counter) {
|
||||||
// Generation counter changed, a dynamic module was either loaded or unloaded.
|
// Generation counter changed, a dynamic module was either loaded or unloaded.
|
||||||
const u32 old_num_dtvs = dtv_table[1].counter;
|
const u32 old_num_dtvs = dtv_table[1].counter;
|
||||||
@ -381,7 +381,7 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
|
|||||||
delete[] dtv_table;
|
delete[] dtv_table;
|
||||||
|
|
||||||
// Update TCB pointer.
|
// Update TCB pointer.
|
||||||
Libraries::Kernel::g_curthread->tcb->tcb_dtv = new_dtv_table;
|
GetTcbBase()->tcb_dtv = new_dtv_table;
|
||||||
dtv_table = new_dtv_table;
|
dtv_table = new_dtv_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,10 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT(result != 0);
|
ASSERT(result != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tcb* GetTcbBase() {
|
||||||
|
return reinterpret_cast<Tcb*>(TlsGetValue(GetTcbKey()));
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Apple x86_64
|
// Apple x86_64
|
||||||
@ -145,6 +149,12 @@ void SetTcbBase(void* image_address) {
|
|||||||
"Failed to store thread LDT page pointer: {}", errno);
|
"Failed to store thread LDT page pointer: {}", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tcb* GetTcbBase() {
|
||||||
|
Tcb* tcb;
|
||||||
|
asm volatile("mov %%fs:0x0, %0" : "=r"(tcb));
|
||||||
|
return tcb;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(ARCH_X86_64)
|
#elif defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Other POSIX x86_64
|
// Other POSIX x86_64
|
||||||
@ -154,6 +164,10 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tcb* GetTcbBase() {
|
||||||
|
return Libraries::Kernel::g_curthread->tcb;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// POSIX non-x86_64
|
// POSIX non-x86_64
|
||||||
@ -176,6 +190,10 @@ void SetTcbBase(void* image_address) {
|
|||||||
ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0);
|
ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tcb* GetTcbBase() {
|
||||||
|
return static_cast<Tcb*>(pthread_getspecific(GetTcbKey()));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread_local std::once_flag init_tls_flag;
|
thread_local std::once_flag init_tls_flag;
|
||||||
|
|||||||
@ -39,6 +39,9 @@ u32 GetTcbKey();
|
|||||||
/// Sets the data pointer to the TCB block.
|
/// Sets the data pointer to the TCB block.
|
||||||
void SetTcbBase(void* image_address);
|
void SetTcbBase(void* image_address);
|
||||||
|
|
||||||
|
/// Retrieves Tcb structure for the calling thread.
|
||||||
|
Tcb* GetTcbBase();
|
||||||
|
|
||||||
/// Makes sure TLS is initialized for the thread before entering guest.
|
/// Makes sure TLS is initialized for the thread before entering guest.
|
||||||
void EnsureThreadInitialized();
|
void EnsureThreadInitialized();
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/thread.h"
|
||||||
#include "imgui/renderer/texture_manager.h"
|
#include "imgui/renderer/texture_manager.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
@ -17,6 +18,8 @@ Scheduler::Scheduler(const Instance& instance)
|
|||||||
profiler_scope = reinterpret_cast<tracy::VkCtxScope*>(std::malloc(sizeof(tracy::VkCtxScope)));
|
profiler_scope = reinterpret_cast<tracy::VkCtxScope*>(std::malloc(sizeof(tracy::VkCtxScope)));
|
||||||
#endif
|
#endif
|
||||||
AllocateWorkerCommandBuffers();
|
AllocateWorkerCommandBuffers();
|
||||||
|
priority_pending_ops_thread =
|
||||||
|
std::jthread(std::bind_front(&Scheduler::PriorityPendingOpsThread, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheduler::~Scheduler() {
|
Scheduler::~Scheduler() {
|
||||||
@ -167,6 +170,32 @@ void Scheduler::SubmitExecution(SubmitInfo& info) {
|
|||||||
PopPendingOperations();
|
PopPendingOperations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scheduler::PriorityPendingOpsThread(std::stop_token stoken) {
|
||||||
|
Common::SetCurrentThreadName("shadPS4:GpuSchedPriorityPendingOpsRunner");
|
||||||
|
|
||||||
|
while (!stoken.stop_requested()) {
|
||||||
|
PendingOp op;
|
||||||
|
{
|
||||||
|
std::unique_lock lk(priority_pending_ops_mutex);
|
||||||
|
priority_pending_ops_cv.wait(lk, stoken,
|
||||||
|
[this] { return !priority_pending_ops.empty(); });
|
||||||
|
if (stoken.stop_requested()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
op = std::move(priority_pending_ops.front());
|
||||||
|
priority_pending_ops.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
master_semaphore.Wait(op.gpu_tick);
|
||||||
|
if (stoken.stop_requested()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
op.callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) {
|
void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) {
|
||||||
if (dirty_state.viewports) {
|
if (dirty_state.viewports) {
|
||||||
dirty_state.viewports = false;
|
dirty_state.viewports = false;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "common/unique_function.h"
|
#include "common/unique_function.h"
|
||||||
@ -401,10 +402,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defers an operation until the gpu has reached the current cpu tick.
|
/// Defers an operation until the gpu has reached the current cpu tick.
|
||||||
|
/// Will be run when submitting or calling PopPendingOperations.
|
||||||
void DeferOperation(Common::UniqueFunction<void>&& func) {
|
void DeferOperation(Common::UniqueFunction<void>&& func) {
|
||||||
pending_ops.emplace(std::move(func), CurrentTick());
|
pending_ops.emplace(std::move(func), CurrentTick());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defers an operation until the gpu has reached the current cpu tick.
|
||||||
|
/// Runs as soon as possible in another thread.
|
||||||
|
void DeferPriorityOperation(Common::UniqueFunction<void>&& func) {
|
||||||
|
{
|
||||||
|
std::unique_lock lk(priority_pending_ops_mutex);
|
||||||
|
priority_pending_ops.emplace(std::move(func), CurrentTick());
|
||||||
|
}
|
||||||
|
priority_pending_ops_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
static std::mutex submit_mutex;
|
static std::mutex submit_mutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -412,6 +424,8 @@ private:
|
|||||||
|
|
||||||
void SubmitExecution(SubmitInfo& info);
|
void SubmitExecution(SubmitInfo& info);
|
||||||
|
|
||||||
|
void PriorityPendingOpsThread(std::stop_token stoken);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
MasterSemaphore master_semaphore;
|
MasterSemaphore master_semaphore;
|
||||||
@ -424,6 +438,10 @@ private:
|
|||||||
u64 gpu_tick;
|
u64 gpu_tick;
|
||||||
};
|
};
|
||||||
std::queue<PendingOp> pending_ops;
|
std::queue<PendingOp> pending_ops;
|
||||||
|
std::queue<PendingOp> priority_pending_ops;
|
||||||
|
std::mutex priority_pending_ops_mutex;
|
||||||
|
std::condition_variable_any priority_pending_ops_cv;
|
||||||
|
std::jthread priority_pending_ops_thread;
|
||||||
RenderState render_state;
|
RenderState render_state;
|
||||||
bool is_rendering = false;
|
bool is_rendering = false;
|
||||||
tracy::VkCtxScope* profiler_scope{};
|
tracy::VkCtxScope* profiler_scope{};
|
||||||
|
|||||||
@ -52,9 +52,6 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
|
|||||||
std::max<u64>(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
std::max<u64>(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||||
DEFAULT_CRITICAL_GC_MEMORY));
|
DEFAULT_CRITICAL_GC_MEMORY));
|
||||||
trigger_gc_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
trigger_gc_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
||||||
|
|
||||||
downloaded_images_thread =
|
|
||||||
std::jthread([&](const std::stop_token& token) { DownloadedImagesThread(token); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::~TextureCache() = default;
|
TextureCache::~TextureCache() = default;
|
||||||
@ -125,33 +122,11 @@ void TextureCache::DownloadImageMemory(ImageId image_id) {
|
|||||||
cmdbuf.copyImageToBuffer(image.GetImage(), vk::ImageLayout::eTransferSrcOptimal,
|
cmdbuf.copyImageToBuffer(image.GetImage(), vk::ImageLayout::eTransferSrcOptimal,
|
||||||
download_buffer.Handle(), image_download);
|
download_buffer.Handle(), image_download);
|
||||||
|
|
||||||
{
|
scheduler.DeferPriorityOperation(
|
||||||
std::unique_lock lock(downloaded_images_mutex);
|
[this, device_addr = image.info.guest_address, download, download_size] {
|
||||||
downloaded_images_queue.emplace(scheduler.CurrentTick(), image.info.guest_address, download,
|
Core::Memory::Instance()->TryWriteBacking(std::bit_cast<u8*>(device_addr), download,
|
||||||
download_size);
|
download_size);
|
||||||
downloaded_images_cv.notify_one();
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureCache::DownloadedImagesThread(const std::stop_token& token) {
|
|
||||||
auto* memory = Core::Memory::Instance();
|
|
||||||
while (!token.stop_requested()) {
|
|
||||||
DownloadedImage image;
|
|
||||||
{
|
|
||||||
std::unique_lock lock{downloaded_images_mutex};
|
|
||||||
downloaded_images_cv.wait(lock, token,
|
|
||||||
[this] { return !downloaded_images_queue.empty(); });
|
|
||||||
if (token.stop_requested()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
image = downloaded_images_queue.front();
|
|
||||||
downloaded_images_queue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduler.GetMasterSemaphore()->Wait(image.tick);
|
|
||||||
memory->TryWriteBacking(std::bit_cast<u8*>(image.device_addr), image.download,
|
|
||||||
image.download_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
|
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
|
||||||
|
|||||||
@ -314,16 +314,6 @@ private:
|
|||||||
Common::LeastRecentlyUsedCache<ImageId, u64> lru_cache;
|
Common::LeastRecentlyUsedCache<ImageId, u64> lru_cache;
|
||||||
PageTable page_table;
|
PageTable page_table;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
struct DownloadedImage {
|
|
||||||
u64 tick;
|
|
||||||
VAddr device_addr;
|
|
||||||
void* download;
|
|
||||||
size_t download_size;
|
|
||||||
};
|
|
||||||
std::queue<DownloadedImage> downloaded_images_queue;
|
|
||||||
std::mutex downloaded_images_mutex;
|
|
||||||
std::condition_variable_any downloaded_images_cv;
|
|
||||||
std::jthread downloaded_images_thread;
|
|
||||||
struct MetaDataInfo {
|
struct MetaDataInfo {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
CMask,
|
CMask,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user