mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-12 20:55:56 +00:00
Merge branch 'main' into fontlib
This commit is contained in:
commit
e82687469c
17 changed files with 163 additions and 42 deletions
|
@ -1100,9 +1100,13 @@ if (ENABLE_DISCORD_RPC)
|
||||||
target_compile_definitions(shadps4 PRIVATE ENABLE_DISCORD_RPC)
|
target_compile_definitions(shadps4 PRIVATE ENABLE_DISCORD_RPC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Optional due to https://github.com/shadps4-emu/shadPS4/issues/1704
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
|
# Optional due to https://github.com/shadps4-emu/shadPS4/issues/1704
|
||||||
target_compile_definitions(shadps4 PRIVATE ENABLE_USERFAULTFD)
|
if (ENABLE_USERFAULTFD)
|
||||||
|
target_compile_definitions(shadps4 PRIVATE ENABLE_USERFAULTFD)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(shadps4 PRIVATE uuid)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|
|
@ -28,8 +28,12 @@
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#include <Rpc.h>
|
#include <Rpc.h>
|
||||||
|
#else
|
||||||
|
#include <uuid/uuid.h>
|
||||||
#endif
|
#endif
|
||||||
#include <common/singleton.h>
|
#include <common/singleton.h>
|
||||||
|
#include <core/libraries/network/net_error.h>
|
||||||
|
#include <core/libraries/network/sockets.h>
|
||||||
#include "aio.h"
|
#include "aio.h"
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
@ -150,23 +154,23 @@ struct OrbisKernelUuid {
|
||||||
u8 clockSeqLow;
|
u8 clockSeqLow;
|
||||||
u8 node[6];
|
u8 node[6];
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(OrbisKernelUuid) == 0x10);
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelUuidCreate(OrbisKernelUuid* orbisUuid) {
|
int PS4_SYSV_ABI sceKernelUuidCreate(OrbisKernelUuid* orbisUuid) {
|
||||||
|
if (!orbisUuid) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
UUID uuid;
|
UUID uuid;
|
||||||
UuidCreate(&uuid);
|
if (UuidCreate(&uuid) != RPC_S_OK) {
|
||||||
orbisUuid->timeLow = uuid.Data1;
|
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||||
orbisUuid->timeMid = uuid.Data2;
|
|
||||||
orbisUuid->timeHiAndVersion = uuid.Data3;
|
|
||||||
orbisUuid->clockSeqHiAndReserved = uuid.Data4[0];
|
|
||||||
orbisUuid->clockSeqLow = uuid.Data4[1];
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
orbisUuid->node[i] = uuid.Data4[2 + i];
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LOG_ERROR(Kernel, "sceKernelUuidCreate: Add linux");
|
uuid_t uuid;
|
||||||
|
uuid_generate(uuid);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
std::memcpy(orbisUuid, &uuid, sizeof(OrbisKernelUuid));
|
||||||
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
|
int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
|
||||||
|
@ -205,6 +209,24 @@ int PS4_SYSV_ABI posix_getpagesize() {
|
||||||
return 16_KB;
|
return 16_KB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_getsockname(Libraries::Net::OrbisNetId s,
|
||||||
|
Libraries::Net::OrbisNetSockaddr* addr, u32* paddrlen) {
|
||||||
|
auto* netcall = Common::Singleton<Libraries::Net::NetInternal>::Instance();
|
||||||
|
auto sock = netcall->FindSocket(s);
|
||||||
|
if (!sock) {
|
||||||
|
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
|
||||||
|
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int returncode = sock->GetSocketAddress(addr, paddrlen);
|
||||||
|
if (returncode >= 0) {
|
||||||
|
LOG_ERROR(Lib_Net, "return code : {:#x}", (u32)returncode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*Libraries::Kernel::__Error() = 0x20;
|
||||||
|
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
||||||
service_thread = std::jthread{KernelServiceThread};
|
service_thread = std::jthread{KernelServiceThread};
|
||||||
|
|
||||||
|
@ -242,8 +264,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom);
|
LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom);
|
||||||
LIB_FUNCTION("fFxGkxF2bVo", "libScePosix", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("fFxGkxF2bVo", "libScePosix", 1, "libkernel", 1, 1,
|
||||||
Libraries::Net::sys_setsockopt);
|
Libraries::Net::sys_setsockopt);
|
||||||
LIB_FUNCTION("RenI1lL1WFk", "libScePosix", 1, "libkernel", 1, 1,
|
// LIB_FUNCTION("RenI1lL1WFk", "libScePosix", 1, "libkernel", 1, 1, posix_getsockname);
|
||||||
Libraries::Net::sys_getsockname);
|
|
||||||
LIB_FUNCTION("KuOmgKoqCdY", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_bind);
|
LIB_FUNCTION("KuOmgKoqCdY", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_bind);
|
||||||
LIB_FUNCTION("5jRCs2axtr4", "libScePosix", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("5jRCs2axtr4", "libScePosix", 1, "libkernel", 1, 1,
|
||||||
Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ...
|
Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ...
|
||||||
|
|
|
@ -17,6 +17,12 @@ int PS4_SYSV_ABI posix_pthread_attr_init(PthreadAttrT* attr);
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_attr_destroy(PthreadAttrT* attr);
|
int PS4_SYSV_ABI posix_pthread_attr_destroy(PthreadAttrT* attr);
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_attr_getaffinity_np(const PthreadAttrT* pattr, size_t cpusetsize,
|
||||||
|
Cpuset* cpusetp);
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_attr_setaffinity_np(PthreadAttrT* pattr, size_t cpusetsize,
|
||||||
|
const Cpuset* cpusetp);
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_create(PthreadT* thread, const PthreadAttrT* attr,
|
int PS4_SYSV_ABI posix_pthread_create(PthreadT* thread, const PthreadAttrT* attr,
|
||||||
PthreadEntryFunc start_routine, void* arg);
|
PthreadEntryFunc start_routine, void* arg);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "core/libraries/kernel/kernel.h"
|
#include "core/libraries/kernel/kernel.h"
|
||||||
#include "core/libraries/kernel/posix_error.h"
|
#include "core/libraries/kernel/posix_error.h"
|
||||||
|
#include "core/libraries/kernel/threads.h"
|
||||||
#include "core/libraries/kernel/threads/pthread.h"
|
#include "core/libraries/kernel/threads/pthread.h"
|
||||||
#include "core/libraries/kernel/threads/thread_state.h"
|
#include "core/libraries/kernel/threads/thread_state.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
|
@ -535,8 +536,6 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
|
||||||
return POSIX_EINVAL;
|
return POSIX_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mask = cpuset->bits;
|
|
||||||
|
|
||||||
uintptr_t handle = native_thr.GetHandle();
|
uintptr_t handle = native_thr.GetHandle();
|
||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
return POSIX_ESRCH;
|
return POSIX_ESRCH;
|
||||||
|
@ -545,6 +544,7 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
|
||||||
// We don't use this currently because some games gets performance problems
|
// We don't use this currently because some games gets performance problems
|
||||||
// when applying affinity even on strong hardware
|
// when applying affinity even on strong hardware
|
||||||
/*
|
/*
|
||||||
|
u64 mask = cpuset->bits;
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
DWORD_PTR affinity_mask = static_cast<DWORD_PTR>(mask);
|
DWORD_PTR affinity_mask = static_cast<DWORD_PTR>(mask);
|
||||||
if (!SetThreadAffinityMask(reinterpret_cast<HANDLE>(handle), affinity_mask)) {
|
if (!SetThreadAffinityMask(reinterpret_cast<HANDLE>(handle), affinity_mask)) {
|
||||||
|
@ -572,13 +572,33 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_getaffinity_np(PthreadT thread, size_t cpusetsize, Cpuset* cpusetp) {
|
||||||
|
if (thread == nullptr || cpusetp == nullptr) {
|
||||||
|
return POSIX_EINVAL;
|
||||||
|
}
|
||||||
|
auto* attr_ptr = &thread->attr;
|
||||||
|
return posix_pthread_attr_getaffinity_np(&attr_ptr, cpusetsize, cpusetp);
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize,
|
int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize,
|
||||||
const Cpuset* cpusetp) {
|
const Cpuset* cpusetp) {
|
||||||
if (thread == nullptr || cpusetp == nullptr) {
|
if (thread == nullptr || cpusetp == nullptr) {
|
||||||
return POSIX_EINVAL;
|
return POSIX_EINVAL;
|
||||||
}
|
}
|
||||||
thread->attr.cpusetsize = cpusetsize;
|
auto* attr_ptr = &thread->attr;
|
||||||
return thread->SetAffinity(cpusetp);
|
if (const auto ret = posix_pthread_attr_setaffinity_np(&attr_ptr, cpusetsize, cpusetp)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return thread->SetAffinity(thread->attr.cpuset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePthreadGetaffinity(PthreadT thread, u64* mask) {
|
||||||
|
Cpuset cpuset;
|
||||||
|
const int ret = posix_pthread_getaffinity_np(thread, sizeof(Cpuset), &cpuset);
|
||||||
|
if (ret == 0) {
|
||||||
|
*mask = cpuset.bits;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadSetaffinity(PthreadT thread, const u64 mask) {
|
int PS4_SYSV_ABI scePthreadSetaffinity(PthreadT thread, const u64 mask) {
|
||||||
|
@ -609,6 +629,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
||||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
|
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
|
||||||
|
LIB_FUNCTION("Jb2uGFMr688", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getaffinity_np);
|
||||||
LIB_FUNCTION("5KWrg7-ZqvE", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setaffinity_np);
|
LIB_FUNCTION("5KWrg7-ZqvE", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setaffinity_np);
|
||||||
|
|
||||||
// Orbis
|
// Orbis
|
||||||
|
@ -632,6 +653,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio));
|
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio));
|
||||||
LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors);
|
LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors);
|
||||||
LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield);
|
LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield);
|
||||||
|
LIB_FUNCTION("rcrVFJsQWRY", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadGetaffinity));
|
||||||
LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadSetaffinity));
|
LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadSetaffinity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,13 +268,13 @@ int PS4_SYSV_ABI posix_pthread_attr_setaffinity_np(PthreadAttrT* pattr, size_t c
|
||||||
attr->cpuset = static_cast<Cpuset*>(calloc(1, sizeof(Cpuset)));
|
attr->cpuset = static_cast<Cpuset*>(calloc(1, sizeof(Cpuset)));
|
||||||
attr->cpusetsize = sizeof(Cpuset);
|
attr->cpusetsize = sizeof(Cpuset);
|
||||||
}
|
}
|
||||||
memcpy(attr->cpuset, cpusetp, cpusetsize);
|
memcpy(attr->cpuset, cpusetp, std::min(cpusetsize, sizeof(Cpuset)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* param_1, u64* mask) {
|
int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* attr, u64* mask) {
|
||||||
Cpuset cpuset;
|
Cpuset cpuset;
|
||||||
const int ret = posix_pthread_attr_getaffinity_np(param_1, sizeof(Cpuset), &cpuset);
|
const int ret = posix_pthread_attr_getaffinity_np(attr, sizeof(Cpuset), &cpuset);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
*mask = cpuset.bits;
|
*mask = cpuset.bits;
|
||||||
}
|
}
|
||||||
|
|
|
@ -886,6 +886,7 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) {
|
int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) {
|
||||||
|
LOG_INFO(Lib_Net, "s={} level={} optname={}", s, level, optname);
|
||||||
if (!g_isNetInitialized) {
|
if (!g_isNetInitialized) {
|
||||||
return ORBIS_NET_ERROR_ENOTINIT;
|
return ORBIS_NET_ERROR_ENOTINIT;
|
||||||
}
|
}
|
||||||
|
@ -1449,6 +1450,7 @@ int PS4_SYSV_ABI sceNetSetDnsInfoToKernel() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval,
|
int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval,
|
||||||
u32 optlen) {
|
u32 optlen) {
|
||||||
|
LOG_INFO(Lib_Net, "s={} level={} optname={} optlen={}", s, level, optname, optlen);
|
||||||
if (!g_isNetInitialized) {
|
if (!g_isNetInitialized) {
|
||||||
return ORBIS_NET_ERROR_ENOTINIT;
|
return ORBIS_NET_ERROR_ENOTINIT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,25 +10,25 @@ namespace Libraries::Net {
|
||||||
|
|
||||||
int P2PSocket::Close() {
|
int P2PSocket::Close() {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
|
int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
int P2PSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
|
int P2PSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int P2PSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
|
int P2PSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int P2PSocket::Listen(int backlog) {
|
int P2PSocket::Listen(int backlog) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
|
int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
|
||||||
|
@ -49,12 +49,12 @@ SocketPtr P2PSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
|
||||||
|
|
||||||
int P2PSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
|
int P2PSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
||||||
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
LOG_ERROR(Lib_Net, "(STUBBED) called");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Net
|
} // namespace Libraries::Net
|
|
@ -143,6 +143,7 @@ static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::Close() {
|
int PosixSocket::Close() {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto out = closesocket(sock);
|
auto out = closesocket(sock);
|
||||||
#else
|
#else
|
||||||
|
@ -152,17 +153,20 @@ int PosixSocket::Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
|
int PosixSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
sockaddr addr2;
|
sockaddr addr2;
|
||||||
convertOrbisNetSockaddrToPosix(addr, &addr2);
|
convertOrbisNetSockaddrToPosix(addr, &addr2);
|
||||||
return ConvertReturnErrorCode(::bind(sock, &addr2, sizeof(sockaddr_in)));
|
return ConvertReturnErrorCode(::bind(sock, &addr2, sizeof(sockaddr_in)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::Listen(int backlog) {
|
int PosixSocket::Listen(int backlog) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
return ConvertReturnErrorCode(::listen(sock, backlog));
|
return ConvertReturnErrorCode(::listen(sock, backlog));
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
|
int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
|
||||||
u32 tolen) {
|
u32 tolen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
if (to != nullptr) {
|
if (to != nullptr) {
|
||||||
sockaddr addr;
|
sockaddr addr;
|
||||||
convertOrbisNetSockaddrToPosix(to, &addr);
|
convertOrbisNetSockaddrToPosix(to, &addr);
|
||||||
|
@ -175,6 +179,7 @@ int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetS
|
||||||
|
|
||||||
int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from,
|
int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from,
|
||||||
u32* fromlen) {
|
u32* fromlen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
if (from != nullptr) {
|
if (from != nullptr) {
|
||||||
sockaddr addr;
|
sockaddr addr;
|
||||||
int res = recvfrom(sock, (char*)buf, len, flags, &addr, (socklen_t*)fromlen);
|
int res = recvfrom(sock, (char*)buf, len, flags, &addr, (socklen_t*)fromlen);
|
||||||
|
@ -187,6 +192,7 @@ int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr*
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
|
SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
sockaddr addr2;
|
sockaddr addr2;
|
||||||
net_socket new_socket = ::accept(sock, &addr2, (socklen_t*)addrlen);
|
net_socket new_socket = ::accept(sock, &addr2, (socklen_t*)addrlen);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -202,12 +208,14 @@ SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
|
int PosixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
sockaddr addr2;
|
sockaddr addr2;
|
||||||
convertOrbisNetSockaddrToPosix(addr, &addr2);
|
convertOrbisNetSockaddrToPosix(addr, &addr2);
|
||||||
return ::connect(sock, &addr2, sizeof(sockaddr_in));
|
return ::connect(sock, &addr2, sizeof(sockaddr_in));
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
sockaddr addr;
|
sockaddr addr;
|
||||||
convertOrbisNetSockaddrToPosix(name, &addr);
|
convertOrbisNetSockaddrToPosix(name, &addr);
|
||||||
if (name != nullptr) {
|
if (name != nullptr) {
|
||||||
|
@ -234,13 +242,15 @@ int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
|
int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
level = ConvertLevels(level);
|
level = ConvertLevels(level);
|
||||||
|
::linger native_linger;
|
||||||
if (level == SOL_SOCKET) {
|
if (level == SOL_SOCKET) {
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
CASE_SETSOCKOPT(SO_REUSEADDR);
|
CASE_SETSOCKOPT(SO_REUSEADDR);
|
||||||
CASE_SETSOCKOPT(SO_KEEPALIVE);
|
CASE_SETSOCKOPT(SO_KEEPALIVE);
|
||||||
CASE_SETSOCKOPT(SO_BROADCAST);
|
CASE_SETSOCKOPT(SO_BROADCAST);
|
||||||
CASE_SETSOCKOPT(SO_LINGER);
|
// CASE_SETSOCKOPT(SO_LINGER);
|
||||||
CASE_SETSOCKOPT(SO_SNDBUF);
|
CASE_SETSOCKOPT(SO_SNDBUF);
|
||||||
CASE_SETSOCKOPT(SO_RCVBUF);
|
CASE_SETSOCKOPT(SO_RCVBUF);
|
||||||
CASE_SETSOCKOPT(SO_SNDTIMEO);
|
CASE_SETSOCKOPT(SO_SNDTIMEO);
|
||||||
|
@ -251,6 +261,24 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
|
||||||
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast);
|
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast);
|
||||||
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto);
|
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto);
|
||||||
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature);
|
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature);
|
||||||
|
case ORBIS_NET_SO_LINGER: {
|
||||||
|
if (socket_type != ORBIS_NET_SOCK_STREAM) {
|
||||||
|
return ORBIS_NET_EPROCUNAVAIL;
|
||||||
|
}
|
||||||
|
if (optlen < sizeof(OrbisNetLinger)) {
|
||||||
|
LOG_ERROR(Lib_Net, "size missmatched! optlen = {} OrbisNetLinger={}", optlen,
|
||||||
|
sizeof(OrbisNetLinger));
|
||||||
|
return ORBIS_NET_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* native_val = &native_linger;
|
||||||
|
u32 native_len = sizeof(native_linger);
|
||||||
|
native_linger.l_onoff = reinterpret_cast<const OrbisNetLinger*>(optval)->l_onoff;
|
||||||
|
native_linger.l_linger = reinterpret_cast<const OrbisNetLinger*>(optval)->l_linger;
|
||||||
|
return ConvertReturnErrorCode(
|
||||||
|
setsockopt(sock, level, SO_LINGER, (const char*)native_val, native_len));
|
||||||
|
}
|
||||||
|
|
||||||
case ORBIS_NET_SO_NAME:
|
case ORBIS_NET_SO_NAME:
|
||||||
return ORBIS_NET_ERROR_EINVAL; // don't support set for name
|
return ORBIS_NET_ERROR_EINVAL; // don't support set for name
|
||||||
case ORBIS_NET_SO_NBIO: {
|
case ORBIS_NET_SO_NBIO: {
|
||||||
|
@ -269,7 +297,7 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
|
||||||
}
|
}
|
||||||
} else if (level == IPPROTO_IP) {
|
} else if (level == IPPROTO_IP) {
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
CASE_SETSOCKOPT(IP_HDRINCL);
|
// CASE_SETSOCKOPT(IP_HDRINCL);
|
||||||
CASE_SETSOCKOPT(IP_TOS);
|
CASE_SETSOCKOPT(IP_TOS);
|
||||||
CASE_SETSOCKOPT(IP_TTL);
|
CASE_SETSOCKOPT(IP_TTL);
|
||||||
CASE_SETSOCKOPT(IP_MULTICAST_IF);
|
CASE_SETSOCKOPT(IP_MULTICAST_IF);
|
||||||
|
@ -279,6 +307,13 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
|
||||||
CASE_SETSOCKOPT(IP_DROP_MEMBERSHIP);
|
CASE_SETSOCKOPT(IP_DROP_MEMBERSHIP);
|
||||||
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_TTLCHK, &sockopt_ip_ttlchk);
|
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_TTLCHK, &sockopt_ip_ttlchk);
|
||||||
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_MAXTTL, &sockopt_ip_maxttl);
|
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_MAXTTL, &sockopt_ip_maxttl);
|
||||||
|
case ORBIS_NET_IP_HDRINCL: {
|
||||||
|
if (socket_type != ORBIS_NET_SOCK_RAW) {
|
||||||
|
return ORBIS_NET_EPROCUNAVAIL;
|
||||||
|
}
|
||||||
|
return ConvertReturnErrorCode(
|
||||||
|
setsockopt(sock, level, optname, (const char*)optval, optlen));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (level == IPPROTO_TCP) {
|
} else if (level == IPPROTO_TCP) {
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
|
@ -311,6 +346,7 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
|
int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
level = ConvertLevels(level);
|
level = ConvertLevels(level);
|
||||||
if (level == SOL_SOCKET) {
|
if (level == SOL_SOCKET) {
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
|
|
|
@ -32,6 +32,10 @@ struct Socket;
|
||||||
|
|
||||||
typedef std::shared_ptr<Socket> SocketPtr;
|
typedef std::shared_ptr<Socket> SocketPtr;
|
||||||
|
|
||||||
|
struct OrbisNetLinger {
|
||||||
|
s32 l_onoff;
|
||||||
|
s32 l_linger;
|
||||||
|
};
|
||||||
struct Socket {
|
struct Socket {
|
||||||
explicit Socket(int domain, int type, int protocol) {}
|
explicit Socket(int domain, int type, int protocol) {}
|
||||||
virtual ~Socket() = default;
|
virtual ~Socket() = default;
|
||||||
|
@ -47,6 +51,7 @@ struct Socket {
|
||||||
u32* fromlen) = 0;
|
u32* fromlen) = 0;
|
||||||
virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0;
|
virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0;
|
||||||
virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0;
|
virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0;
|
||||||
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PosixSocket : public Socket {
|
struct PosixSocket : public Socket {
|
||||||
|
@ -59,8 +64,11 @@ struct PosixSocket : public Socket {
|
||||||
int sockopt_ip_ttlchk = 0;
|
int sockopt_ip_ttlchk = 0;
|
||||||
int sockopt_ip_maxttl = 0;
|
int sockopt_ip_maxttl = 0;
|
||||||
int sockopt_tcp_mss_to_advertise = 0;
|
int sockopt_tcp_mss_to_advertise = 0;
|
||||||
|
int socket_type;
|
||||||
explicit PosixSocket(int domain, int type, int protocol)
|
explicit PosixSocket(int domain, int type, int protocol)
|
||||||
: Socket(domain, type, protocol), sock(socket(domain, type, protocol)) {}
|
: Socket(domain, type, protocol), sock(socket(domain, type, protocol)) {
|
||||||
|
socket_type = type;
|
||||||
|
}
|
||||||
explicit PosixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {}
|
explicit PosixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {}
|
||||||
int Close() override;
|
int Close() override;
|
||||||
int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override;
|
int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "sys_net.h"
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
|
@ -649,19 +649,23 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t s
|
||||||
s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
s64 protected_bytes = 0;
|
s64 protected_bytes = 0;
|
||||||
|
|
||||||
|
auto aligned_addr = Common::AlignDown(addr, 16_KB);
|
||||||
|
auto aligned_size = Common::AlignUp(size + addr - aligned_addr, 16_KB);
|
||||||
do {
|
do {
|
||||||
auto it = FindVMA(addr + protected_bytes);
|
auto it = FindVMA(aligned_addr + protected_bytes);
|
||||||
auto& vma_base = it->second;
|
auto& vma_base = it->second;
|
||||||
ASSERT_MSG(vma_base.Contains(addr + protected_bytes, 0), "Address {:#x} is out of bounds",
|
ASSERT_MSG(vma_base.Contains(addr + protected_bytes, 0), "Address {:#x} is out of bounds",
|
||||||
addr + protected_bytes);
|
addr + protected_bytes);
|
||||||
auto result = 0;
|
auto result = 0;
|
||||||
result = ProtectBytes(addr + protected_bytes, vma_base, size - protected_bytes, prot);
|
result = ProtectBytes(aligned_addr + protected_bytes, vma_base,
|
||||||
|
aligned_size - protected_bytes, prot);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
// ProtectBytes returned an error, return it
|
// ProtectBytes returned an error, return it
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
protected_bytes += result;
|
protected_bytes += result;
|
||||||
} while (protected_bytes < size);
|
} while (protected_bytes < aligned_size);
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
void* memset(void* ptr, int value, size_t num);
|
|
||||||
|
|
||||||
namespace Xbyak {
|
namespace Xbyak {
|
||||||
class CodeGenerator;
|
class CodeGenerator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
|
||||||
float angle = atan2(d_y, d_x);
|
float angle = atan2(d_y, d_x);
|
||||||
float a_x = cos(angle) * output_speed, a_y = sin(angle) * output_speed;
|
float a_x = cos(angle) * output_speed, a_y = sin(angle) * output_speed;
|
||||||
|
|
||||||
if (d_x != 0 && d_y != 0) {
|
if (d_x != 0 || d_y != 0) {
|
||||||
controller->Axis(0, axis_x, GetAxis(-0x80, 0x7f, a_x));
|
controller->Axis(0, axis_x, GetAxis(-0x80, 0x7f, a_x));
|
||||||
controller->Axis(0, axis_y, GetAxis(-0x80, 0x7f, a_y));
|
controller->Axis(0, axis_y, GetAxis(-0x80, 0x7f, a_y));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -62,7 +62,14 @@ struct BufferResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsStorage(const AmdGpu::Buffer& buffer, const Profile& profile) const noexcept {
|
bool IsStorage(const AmdGpu::Buffer& buffer, const Profile& profile) const noexcept {
|
||||||
return buffer.GetSize() > profile.max_ubo_size || is_written;
|
// When using uniform buffers, a size is required at compilation time, so we need to
|
||||||
|
// either compile a lot of shader specializations to handle each size or just force it to
|
||||||
|
// the maximum possible size always. However, for some vendors the shader-supplied size is
|
||||||
|
// used for bounds checking uniform buffer accesses, so the latter would effectively turn
|
||||||
|
// off buffer robustness behavior. Instead, force storage buffers which are bounds checked
|
||||||
|
// using the actual buffer size. We are assuming the performance hit from this is
|
||||||
|
// acceptable.
|
||||||
|
return true; // buffer.GetSize() > profile.max_ubo_size || is_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept;
|
[[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept;
|
||||||
|
|
|
@ -238,7 +238,15 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo
|
||||||
.bufferMemoryBarrierCount = 1,
|
.bufferMemoryBarrierCount = 1,
|
||||||
.pBufferMemoryBarriers = &pre_barrier,
|
.pBufferMemoryBarriers = &pre_barrier,
|
||||||
});
|
});
|
||||||
cmdbuf.updateBuffer(buffer->Handle(), buffer->Offset(address), num_bytes, value);
|
// vkCmdUpdateBuffer can only copy up to 65536 bytes at a time.
|
||||||
|
static constexpr u32 UpdateBufferMaxSize = 65536;
|
||||||
|
const auto dst_offset = buffer->Offset(address);
|
||||||
|
for (u32 offset = 0; offset < num_bytes; offset += UpdateBufferMaxSize) {
|
||||||
|
const auto* update_src = static_cast<const u8*>(value) + offset;
|
||||||
|
const auto update_dst = dst_offset + offset;
|
||||||
|
const auto update_size = std::min(num_bytes - offset, UpdateBufferMaxSize);
|
||||||
|
cmdbuf.updateBuffer(buffer->Handle(), update_dst, update_size, update_src);
|
||||||
|
}
|
||||||
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
.bufferMemoryBarrierCount = 1,
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
|
|
@ -261,6 +261,8 @@ bool Instance::CreateDevice() {
|
||||||
robustness2_features = feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
robustness2_features = feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
||||||
LOG_INFO(Render_Vulkan, "- robustBufferAccess2: {}",
|
LOG_INFO(Render_Vulkan, "- robustBufferAccess2: {}",
|
||||||
robustness2_features.robustBufferAccess2);
|
robustness2_features.robustBufferAccess2);
|
||||||
|
LOG_INFO(Render_Vulkan, "- robustImageAccess2: {}",
|
||||||
|
robustness2_features.robustImageAccess2);
|
||||||
LOG_INFO(Render_Vulkan, "- nullDescriptor: {}", robustness2_features.nullDescriptor);
|
LOG_INFO(Render_Vulkan, "- nullDescriptor: {}", robustness2_features.nullDescriptor);
|
||||||
}
|
}
|
||||||
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||||
|
@ -337,6 +339,7 @@ bool Instance::CreateDevice() {
|
||||||
.independentBlend = features.independentBlend,
|
.independentBlend = features.independentBlend,
|
||||||
.geometryShader = features.geometryShader,
|
.geometryShader = features.geometryShader,
|
||||||
.tessellationShader = features.tessellationShader,
|
.tessellationShader = features.tessellationShader,
|
||||||
|
.dualSrcBlend = features.dualSrcBlend,
|
||||||
.logicOp = features.logicOp,
|
.logicOp = features.logicOp,
|
||||||
.multiDrawIndirect = features.multiDrawIndirect,
|
.multiDrawIndirect = features.multiDrawIndirect,
|
||||||
.depthBiasClamp = features.depthBiasClamp,
|
.depthBiasClamp = features.depthBiasClamp,
|
||||||
|
@ -394,6 +397,7 @@ bool Instance::CreateDevice() {
|
||||||
},
|
},
|
||||||
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
||||||
.robustBufferAccess2 = robustness2_features.robustBufferAccess2,
|
.robustBufferAccess2 = robustness2_features.robustBufferAccess2,
|
||||||
|
.robustImageAccess2 = robustness2_features.robustImageAccess2,
|
||||||
.nullDescriptor = robustness2_features.nullDescriptor,
|
.nullDescriptor = robustness2_features.nullDescriptor,
|
||||||
},
|
},
|
||||||
vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{
|
vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{
|
||||||
|
|
|
@ -205,7 +205,8 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
||||||
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
|
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
|
||||||
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
|
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
|
||||||
.supports_trinary_minmax = instance_.IsAmdShaderTrinaryMinMaxSupported(),
|
.supports_trinary_minmax = instance_.IsAmdShaderTrinaryMinMaxSupported(),
|
||||||
.supports_robust_buffer_access = instance_.IsRobustBufferAccess2Supported(),
|
// TODO: Emitted bounds checks cause problems with phi control flow; needs to be fixed.
|
||||||
|
.supports_robust_buffer_access = true, // instance_.IsRobustBufferAccess2Supported(),
|
||||||
.supports_image_fp32_atomic_min_max = instance_.IsShaderAtomicFloatImage32MinMaxSupported(),
|
.supports_image_fp32_atomic_min_max = instance_.IsShaderAtomicFloatImage32MinMaxSupported(),
|
||||||
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
|
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
|
||||||
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
|
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue