From 2ab5cfb1f3cfe357f19039ad221cf302d13fca1b Mon Sep 17 00:00:00 2001 From: DH Date: Sat, 24 Jun 2023 23:48:25 +0300 Subject: [PATCH] Add OS<->GPU IPC --- .../bridge/include/amdgpu/bridge/bridge.hpp | 54 ++++---- hw/amdgpu/bridge/src/bridge.cpp | 7 +- rpcsx-gpu/main.cpp | 100 ++++++++++++-- rpcsx-os/CMakeLists.txt | 3 +- rpcsx-os/bridge.cpp | 4 + rpcsx-os/bridge.hpp | 7 + rpcsx-os/iodev/dce.cpp | 75 +++-------- rpcsx-os/iodev/gc.cpp | 5 +- rpcsx-os/main.cpp | 126 +++++++++++++++--- rpcsx-os/vm.cpp | 14 +- 10 files changed, 271 insertions(+), 124 deletions(-) create mode 100644 rpcsx-os/bridge.cpp create mode 100644 rpcsx-os/bridge.hpp diff --git a/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp b/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp index 1f017374b..12743cefe 100644 --- a/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp +++ b/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp @@ -83,18 +83,17 @@ enum class BridgeFlags { PullLock = 1 << 2, }; -class BridgePusher { - BridgeHeader *buffer = nullptr; +struct BridgePusher { + BridgeHeader *header = nullptr; -public: BridgePusher() = default; - BridgePusher(BridgeHeader *buffer) : buffer(buffer) {} + BridgePusher(BridgeHeader *header) : header(header) {} void setVm(std::uint64_t address, std::uint64_t size, const char *name) { - buffer->vmAddress = address; - buffer->vmSize = size; - std::strncpy(buffer->vmName, name, sizeof(buffer->vmName)); - buffer->flags |= static_cast(BridgeFlags::VmConfigured); + header->vmAddress = address; + header->vmSize = size; + std::strncpy(header->vmName, name, sizeof(header->vmName)); + header->flags |= static_cast(BridgeFlags::VmConfigured); } void sendMemoryProtect(std::uint64_t address, std::uint64_t size, @@ -124,7 +123,7 @@ public: void sendDoFlip() { sendCommand(CommandId::DoFlip, {}); } void wait() { - while (buffer->pull != buffer->push) + while (header->pull != header->push) ; } @@ -138,21 +137,21 @@ private: std::size_t cmdSize = args.size() + 1; std::uint64_t pos = getPushPosition(cmdSize); - buffer->commands[pos++] = makeCommandHeader(CommandId::Flip, cmdSize); + header->commands[pos++] = makeCommandHeader(CommandId::Flip, cmdSize); for (auto arg : args) { - buffer->commands[pos++] = arg; + header->commands[pos++] = arg; } - buffer->push = pos; + header->push = pos; } std::uint64_t getPushPosition(std::uint64_t cmdSize) { - std::uint64_t position = buffer->push; + std::uint64_t position = header->push; - if (position + cmdSize > buffer->size) { - if (position < buffer->size) { - buffer->commands[position] = + if (position + cmdSize > header->size) { + if (position < header->size) { + header->commands[position] = static_cast(CommandId::Nop) | - ((buffer->size - position - 1) << 32); + ((header->size - position - 1) << 32); } position = 0; @@ -162,44 +161,43 @@ private: return position; } void waitPuller(std::uint64_t pullValue) { - while (buffer->pull < pullValue) { + while (header->pull < pullValue) { ; } } }; -class BridgePuller { - BridgeHeader *buffer = nullptr; +struct BridgePuller { + BridgeHeader *header = nullptr; -public: BridgePuller() = default; - BridgePuller(BridgeHeader *buffer) : buffer(buffer) {} + BridgePuller(BridgeHeader *header) : header(header) {} std::size_t pullCommands(Command *commands, std::size_t maxCount) { std::size_t processed = 0; while (processed < maxCount) { - if (buffer->pull == buffer->push) { + if (header->pull == header->push) { break; } - auto pos = buffer->pull; - auto cmd = buffer->commands[pos]; + auto pos = header->pull; + auto cmd = header->commands[pos]; CommandId cmdId = static_cast(cmd); std::uint32_t argsCount = cmd >> 32; if (cmdId != CommandId::Nop) { commands[processed++] = - unpackCommand(cmdId, buffer->commands + pos + 1, argsCount); + unpackCommand(cmdId, header->commands + pos + 1, argsCount); } auto newPull = pos + argsCount + 1; - if (newPull >= buffer->size) { + if (newPull >= header->size) { newPull = 0; } - buffer->pull = newPull; + header->pull = newPull; } return processed; diff --git a/hw/amdgpu/bridge/src/bridge.cpp b/hw/amdgpu/bridge/src/bridge.cpp index d32c940af..0d38f9410 100644 --- a/hw/amdgpu/bridge/src/bridge.cpp +++ b/hw/amdgpu/bridge/src/bridge.cpp @@ -14,7 +14,7 @@ amdgpu::bridge::createShmCommandBuffer(const char *name) { return nullptr; } - unlinkShm(name); + // unlinkShm(name); int fd = ::shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); @@ -54,6 +54,11 @@ amdgpu::bridge::openShmCommandBuffer(const char *name) { return nullptr; } + if (ftruncate(fd, kShmSize) < 0) { + ::close(fd); + return nullptr; + } + void *memory = ::mmap(nullptr, kShmSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); diff --git a/rpcsx-gpu/main.cpp b/rpcsx-gpu/main.cpp index 15fb909ad..84fd47868 100644 --- a/rpcsx-gpu/main.cpp +++ b/rpcsx-gpu/main.cpp @@ -2,11 +2,17 @@ #include #include #include +#include #include +#include +#include #include +#include #include #include #include +#include +#include #include // TODO: make in optional @@ -262,8 +268,8 @@ int main(int argc, const char *argv[]) { &queueFamilyCount, nullptr); Verify() << (queueFamilyCount > 0); queueFamilyProperties.resize(queueFamilyCount); - for (auto &propery : queueFamilyProperties) { - propery.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + for (auto &property : queueFamilyProperties) { + property.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; } vkGetPhysicalDeviceQueueFamilyProperties2( @@ -424,27 +430,33 @@ int main(int argc, const char *argv[]) { &vkDevice); - std::vector computeQueues; - std::vector transferQueues; - std::vector graphicsQueues; + std::vector> computeQueues; + std::vector> transferQueues; + std::vector> graphicsQueues; VkQueue presentQueue = VK_NULL_HANDLE; for (auto &queueInfo : requestedQueues) { if (queueFamiliesWithComputeSupport.contains(queueInfo.queueFamilyIndex)) { for (uint32_t queueIndex = 0; queueIndex < queueInfo.queueCount; ++queueIndex) { - vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &computeQueues.emplace_back()); + auto &[queue, index] = computeQueues.emplace_back(); + index = queueInfo.queueFamilyIndex; + vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &queue); } } if (queueFamiliesWithGraphicsSupport.contains(queueInfo.queueFamilyIndex)) { for (uint32_t queueIndex = 0; queueIndex < queueInfo.queueCount; ++queueIndex) { - vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &graphicsQueues.emplace_back()); + auto &[queue, index] = graphicsQueues.emplace_back(); + index = queueInfo.queueFamilyIndex; + vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &queue); } } if (queueFamiliesWithTransferSupport.contains(queueInfo.queueFamilyIndex)) { for (uint32_t queueIndex = 0; queueIndex < queueInfo.queueCount; ++queueIndex) { - vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &transferQueues.emplace_back()); + auto &[queue, index] = transferQueues.emplace_back(); + index = queueInfo.queueFamilyIndex; + vkGetDeviceQueue(vkDevice, queueInfo.queueFamilyIndex, queueIndex, &queue); } } @@ -460,16 +472,56 @@ int main(int argc, const char *argv[]) { amdgpu::device::setVkDevice(vkDevice, vkPhyDeviceMemoryProperties); - std::printf("Initialization was succesful\n"); + std::printf("Initialization was successful\n"); // TODO: open emulator shared memory - auto bridge = amdgpu::bridge::createShmCommandBuffer(cmdBridgeName); + auto bridge = amdgpu::bridge::openShmCommandBuffer(cmdBridgeName); + if (bridge == nullptr) { + bridge = amdgpu::bridge::createShmCommandBuffer(cmdBridgeName); + } + + if (bridge->pullerPid > 0 && ::kill(bridge->pullerPid, 0) == 0) { + // another instance of rpcsx-gpu on the same bridge, kill self after that + + std::fprintf(stderr, "Another instance already exists\n"); + return 1; + } + + bridge->pullerPid = ::getpid(); amdgpu::bridge::BridgePuller bridgePuller { bridge }; amdgpu::bridge::Command commandsBuffer[32]; - amdgpu::device::DrawContext dc{ - // TODO + int memoryFd = ::shm_open(shmName, O_RDWR, S_IRUSR | S_IWUSR); + + if (memoryFd < 0) { + std::printf("failed to open shared memory\n"); + } + + struct stat memoryStat; + ::fstat(memoryFd, &memoryStat); + amdgpu::RemoteMemory memory { + (char *)::mmap(nullptr, memoryStat.st_size, PROT_NONE, MAP_SHARED, memoryFd, 0) + }; + + VkCommandPoolCreateInfo commandPoolCreateInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .queueFamilyIndex = graphicsQueues.front().second + }; + + VkCommandPool commandPool; + Verify() << vkCreateCommandPool(vkDevice, &commandPoolCreateInfo, nullptr, &commandPool); + + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, + }; + + VkPipelineCache pipelineCache; + Verify() << vkCreatePipelineCache(vkDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache); + amdgpu::device::DrawContext dc{ // TODO + .pipelineCache = pipelineCache, + .queue = graphicsQueues.front().first, + .commandPool = commandPool, }; amdgpu::device::AmdgpuDevice device{ dc }; @@ -484,11 +536,31 @@ int main(int argc, const char *argv[]) { continue; } - for (std::size_t i = 0; i < pulledCount; ++i) { - // TODO: handle command + for (auto cmd : std::span(commandsBuffer, pulledCount)) { + switch (cmd.id) { + case amdgpu::bridge::CommandId::SetUpSharedMemory: + break; + case amdgpu::bridge::CommandId::ProtectMemory: + break; + case amdgpu::bridge::CommandId::CommandBuffer: + break; + case amdgpu::bridge::CommandId::Flip: + break; + case amdgpu::bridge::CommandId::DoFlip: + break; + case amdgpu::bridge::CommandId::SetBuffer: + break; + + default: + util::unreachable("Unexpected command id %u\n", (unsigned)cmd.id); + } } } + if (bridge->pusherPid > 0) { + kill(bridge->pusherPid, SIGINT); + } + amdgpu::bridge::destroyShmCommandBuffer(bridge); amdgpu::bridge::unlinkShm(cmdBridgeName); return 0; diff --git a/rpcsx-os/CMakeLists.txt b/rpcsx-os/CMakeLists.txt index 7ee390d71..6ce09b7ad 100644 --- a/rpcsx-os/CMakeLists.txt +++ b/rpcsx-os/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable(rpcsx-os iodev/zero.cpp main.cpp + bridge.cpp vm.cpp ops.cpp linker.cpp @@ -27,7 +28,7 @@ add_executable(rpcsx-os vfs.cpp ) target_include_directories(rpcsx-os PUBLIC .) -target_link_libraries(rpcsx-os PUBLIC orbis::kernel libcrypto unwind unwind-x86_64) +target_link_libraries(rpcsx-os PUBLIC orbis::kernel amdgpu::bridge libcrypto unwind unwind-x86_64) target_link_options(rpcsx-os PUBLIC "LINKER:-Ttext-segment,0x0000010000000000") target_compile_options(rpcsx-os PRIVATE "-march=native") diff --git a/rpcsx-os/bridge.cpp b/rpcsx-os/bridge.cpp new file mode 100644 index 000000000..75e750a50 --- /dev/null +++ b/rpcsx-os/bridge.cpp @@ -0,0 +1,4 @@ +#include "bridge.hpp" + +amdgpu::bridge::BridgePusher rx::bridge; + diff --git a/rpcsx-os/bridge.hpp b/rpcsx-os/bridge.hpp new file mode 100644 index 000000000..21c9f904a --- /dev/null +++ b/rpcsx-os/bridge.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rx { +extern amdgpu::bridge::BridgePusher bridge; +} diff --git a/rpcsx-os/iodev/dce.cpp b/rpcsx-os/iodev/dce.cpp index 4726330d0..8b48a2711 100644 --- a/rpcsx-os/iodev/dce.cpp +++ b/rpcsx-os/iodev/dce.cpp @@ -1,3 +1,4 @@ +#include "bridge.hpp" #include "io-device.hpp" #include #include @@ -15,54 +16,8 @@ struct VideoOutBuffer { struct DceDevice : public IoDevice {}; -// template -// inline bool -// atomic_compare_exchange_weak(volatile T *ptr, T *expected, T desired, -// int successMemOrder = __ATOMIC_SEQ_CST, -// int failureMemOrder = __ATOMIC_SEQ_CST) { -// return __atomic_compare_exchange_n(ptr, expected, desired, true, -// __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); -// } - struct DceInstance : public IoDeviceInstance { VideoOutBuffer bufferAttributes{}; - - // std::uint64_t flipStatusOffset = - // mem::allocateInternal(sizeof(liverpool::bridge::FlipStatus), - // alignof(liverpool::bridge::FlipStatus)); - // liverpool::bridge::FlipStatus *flipStatus = new ( - // mem::mapInternal(flipStatusOffset, sizeof(liverpool::bridge::FlipStatus))) - // liverpool::bridge::FlipStatus(); - - DceInstance() { - // *flipStatus = {}; - // orbis::bridge.sendSetFlipStatus(flipStatusOffset); - } - void registerBuffer(int index, std::uint64_t address) { - // orbis::bridge.sendSetBuffer(index, address, bufferAttributes.width, - // bufferAttributes.height, bufferAttributes.pitch, - // bufferAttributes.pixelFormat, - // bufferAttributes.tilingMode); - } - - void flip(std::uint32_t bufferIndex, std::uint64_t flipMode, - std::uint64_t flipArg) { - - // orbis::bridge.sendFlip(bufferIndex, flipArg); - // orbis::bridge.wait(); - } - - // liverpool::bridge::FlipStatus getFlipStatus() { - // int expected = 0; - // while (!atomic_compare_exchange_weak(&flipStatus->locked, &expected, 1)) { - // expected = 0; - // } - - // liverpool::bridge::FlipStatus result = *flipStatus; - // flipStatus->locked = 0; - - // return result; - // } }; struct RegisterBuffer { @@ -149,14 +104,13 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, return 0; } - // auto currentStatus = dceInstance->getFlipStatus(); - FlipControlStatus flipStatus{}; - // flipStatus.flipArg = currentStatus.arg; - // flipStatus.count = currentStatus.count; + // TODO: lock bridge header + flipStatus.flipArg = rx::bridge.header->flipArg; + flipStatus.count = rx::bridge.header->flipCount; flipStatus.processTime = 0; // TODO flipStatus.tsc = 0; // TODO - // flipStatus.currentBuffer = currentStatus.currentBuffer; + flipStatus.currentBuffer = rx::bridge.header->flipBuffer; flipStatus.unkQueueNum = 0; // TODO flipStatus.gcQueueNum = 0; // TODO flipStatus.unk2QueueNum = 0; // TODO @@ -196,7 +150,22 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, std::fprintf(stderr, "dce: RegisterBuffer(%lx, %lx, %lx, %lx)\n", args->attributeIndex, args->index, args->address, args->unk); - dceInstance->registerBuffer(args->index, args->address); + + if (args->index >= std::size(rx::bridge.header->buffers)) { + // TODO + std::fprintf(stderr, "dce: out of buffers!\n"); + return -1; + } + + // TODO: lock bridge header + rx::bridge.header->buffers[args->index] = { + .bufferIndex = static_cast(args->index), + .width = dceInstance->bufferAttributes.width, + .height = dceInstance->bufferAttributes.height, + .pitch = dceInstance->bufferAttributes.pitch, + .pixelFormat = dceInstance->bufferAttributes.pixelFormat, + .tilingMode = dceInstance->bufferAttributes.tilingMode + }; return 0; } @@ -235,7 +204,7 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, args->arg1, args->displayBufferIndex, args->flipMode, args->flipArg, args->arg5, args->arg6, args->arg7, args->arg8); - dceInstance->flip(args->displayBufferIndex, args->flipMode, args->flipArg); + rx::bridge.sendFlip(args->displayBufferIndex, /*args->flipMode,*/ args->flipArg); if (args->flipMode == 1 || args->arg7 == 0) { // orbis::bridge.sendDoFlip(); diff --git a/rpcsx-os/iodev/gc.cpp b/rpcsx-os/iodev/gc.cpp index 4867a95a2..5714160cb 100644 --- a/rpcsx-os/iodev/gc.cpp +++ b/rpcsx-os/iodev/gc.cpp @@ -1,3 +1,4 @@ +#include "bridge.hpp" #include "io-device.hpp" #include #include @@ -58,7 +59,7 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, std::fprintf(stderr, " unkPreservedVal = %lx\n", unkPreservedVal); std::fprintf(stderr, " size = %lu\n", size); - // orbis::bridge.sendCommandBuffer(address, size); + rx::bridge.sendCommandBuffer(cmdId, address, size); } break; @@ -108,7 +109,7 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, std::fprintf(stderr, " unkPreservedVal = %lx\n", unkPreservedVal); std::fprintf(stderr, " size = %lu\n", size); - // orbis::bridge.sendCommandBuffer(address, size); + rx::bridge.sendCommandBuffer(cmdId, address, size); } //orbis::bridge.sendDoFlip(); diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index c355d1243..ee52bbcb5 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -1,4 +1,6 @@ #include "align.hpp" +#include "amdgpu/bridge/bridge.hpp" +#include "bridge.hpp" #include "io-device.hpp" #include "io-devices.hpp" #include "linker.hpp" @@ -6,6 +8,8 @@ #include "vfs.hpp" #include "vm.hpp" +#include +#include #include #include #include @@ -27,6 +31,8 @@ #include #include +static int g_gpuPid; + struct LibcInfo { std::uint64_t textBegin = ~static_cast(0); std::uint64_t textSize = 0; @@ -159,7 +165,9 @@ static void printStackTrace(ucontext_t *context, orbis::Thread *thread, __attribute__((no_stack_protector)) static void handle_signal(int sig, siginfo_t *info, void *ucontext) { std::uint64_t hostFs = _readgsbase_u64(); - _writefsbase_u64(hostFs); + if (hostFs != 0) { + _writefsbase_u64(hostFs); + } // syscall(SYS_arch_prctl, ARCH_GET_GS, &hostFs); // syscall(SYS_arch_prctl, ARCH_SET_FS, hostFs); @@ -173,20 +181,32 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { return; } - const char message[] = "Signal handler!\n"; - write(2, message, sizeof(message) - 1); + if (g_gpuPid > 0) { + // stop gpu thread + ::kill(g_gpuPid, SIGINT); + } - char buf[128] = ""; - int len = snprintf(buf, sizeof(buf), " [%s] %u: Signal address=%p\n", - g_currentThread ? "guest" : "host", - g_currentThread ? g_currentThread->tid : ::gettid(), - info->si_addr); - write(2, buf, len); + if (sig != SIGINT) { + char buf[128] = ""; + int len = snprintf(buf, sizeof(buf), " [%s] %u: Signal address=%p\n", + g_currentThread ? "guest" : "host", + g_currentThread ? g_currentThread->tid : ::gettid(), + info->si_addr); + write(2, buf, len); - if (std::size_t printed = printAddressLocation( - buf, sizeof(buf), g_currentThread, (std::uint64_t)info->si_addr)) { - printed += std::snprintf(buf + printed, sizeof(buf) - printed, "\n"); - write(2, buf, printed); + if (std::size_t printed = printAddressLocation( + buf, sizeof(buf), g_currentThread, (std::uint64_t)info->si_addr)) { + printed += std::snprintf(buf + printed, sizeof(buf) - printed, "\n"); + write(2, buf, printed); + } + + + if (g_currentThread) { + printStackTrace(reinterpret_cast(ucontext), g_currentThread, + 2); + } else { + printStackTrace(reinterpret_cast(ucontext), 2); + } } struct sigaction act {}; @@ -202,11 +222,8 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { std::exit(-1); } - if (g_currentThread) { - printStackTrace(reinterpret_cast(ucontext), g_currentThread, - 2); - } else { - printStackTrace(reinterpret_cast(ucontext), 2); + if (sig == SIGINT) { + std::raise(SIGINT); } } @@ -260,6 +277,11 @@ static void setupSigHandlers() { perror("Error sigaction:"); exit(-1); } + + if (sigaction(SIGINT, &act, NULL)) { + perror("Error sigaction:"); + exit(-1); + } } __attribute__((no_stack_protector)) static void * @@ -515,6 +537,72 @@ static void usage(const char *argv0) { std::printf(" --trace\n"); } +static std::filesystem::path getSelfDir() { + char path[PATH_MAX]; + int len = ::readlink("/proc/self/exe", path, sizeof(path)); + if (len < 0 || len >= sizeof(path)) { + // TODO + return std::filesystem::current_path(); + } + + return std::filesystem::path(path).parent_path(); +} + +static bool isRpsxGpuPid(int pid) { + if (pid <= 0 || ::kill(pid, 0) != 0) { + return false; + } + + char path[PATH_MAX]; + std::string procPath = "/proc/" + std::to_string(pid) + "/exe"; + auto len = ::readlink(procPath.c_str(), path, sizeof(path)); + + if (len < 0 || len >= std::size(path)) { + return false; + } + + path[len] = 0; + + std::printf("filename is '%s'\n", std::filesystem::path(path).filename().c_str()); + + return std::filesystem::path(path).filename() == "rpcsx-gpu"; +} +static void runRpsxGpu() { + const char *cmdBufferName = "/rpcsx-gpu-cmds"; + amdgpu::bridge::BridgeHeader *bridgeHeader = amdgpu::bridge::openShmCommandBuffer(cmdBufferName); + + if (bridgeHeader != nullptr && bridgeHeader->pullerPid > 0 && isRpsxGpuPid(bridgeHeader->pullerPid)) { + bridgeHeader->pusherPid = ::getpid(); + g_gpuPid = bridgeHeader->pullerPid; + rx::bridge = bridgeHeader; + return; + } + + std::printf("Starting rpcsx-gpu\n"); + + if (bridgeHeader == nullptr) { + bridgeHeader = amdgpu::bridge::createShmCommandBuffer(cmdBufferName); + } + bridgeHeader->pusherPid = ::getpid(); + rx::bridge = bridgeHeader; + + auto rpcsxGpuPath = getSelfDir() / "rpcsx-gpu"; + + if (!std::filesystem::is_regular_file(rpcsxGpuPath)) { + std::printf("failed to find rpcsx-gpu, continue without GPU emulation\n"); + return; + } + + g_gpuPid = ::fork(); + + if (g_gpuPid == 0) { + // TODO + const char *argv[] = {rpcsxGpuPath.c_str(), nullptr}; + + ::execv(rpcsxGpuPath.c_str(), const_cast(argv)); + } +} + int main(int argc, const char *argv[]) { if (argc == 2) { if (std::strcmp(argv[1], "-h") == 0 || @@ -606,6 +694,8 @@ int main(int argc, const char *argv[]) { } rx::vm::initialize(); + runRpsxGpu(); + // rx::vm::printHostStats(); auto initProcess = context.createProcess(10); initProcess->sysent = &orbis::ps4_sysvec; diff --git a/rpcsx-os/vm.cpp b/rpcsx-os/vm.cpp index 8e8ce96df..ae098bf66 100644 --- a/rpcsx-os/vm.cpp +++ b/rpcsx-os/vm.cpp @@ -1,5 +1,6 @@ #include "vm.hpp" #include "align.hpp" +#include "bridge.hpp" #include #include #include @@ -596,15 +597,15 @@ static void reserve(std::uint64_t startAddress, std::uint64_t endAddress) { void rx::vm::initialize() { std::printf("Memory: initialization\n"); - gMemoryShm = ::shm_open("/orbis-memory", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + gMemoryShm = ::shm_open("/rpcsx-os-memory", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (gMemoryShm == -1) { - std::printf("Memory: failed to open /orbis-memory\n"); + std::printf("Memory: failed to open /rpcsx-os-memory\n"); std::abort(); } if (::ftruncate64(gMemoryShm, kMemorySize) < 0) { - std::printf("Memory: failed to allocate /orbis-memory\n"); + std::printf("Memory: failed to allocate /rpcsx-os-memory\n"); std::abort(); } @@ -798,7 +799,6 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot, allocInfo.flags = kBlockFlagDirectMemory; // TODO allocInfo.name[0] = '\0'; // TODO - // orbis::bridge.sendMemoryProtect(address, len, prot); auto result = utils::map(reinterpret_cast(address), len, prot & kMapProtCpuAll, realFlags, gMemoryShm, address - kMinAddress); @@ -814,6 +814,7 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot, } } + rx::bridge.sendMemoryProtect(address, len, prot); return result; } @@ -841,7 +842,7 @@ bool rx::vm::unmap(void *addr, std::uint64_t size) { gBlocks[(address >> kBlockShift) - kFirstBlock].removeFlags( (address & kBlockMask) >> kPageShift, pages, ~0); - // orbis::bridge.sendMemoryProtect(address, size, 0); + rx::bridge.sendMemoryProtect(reinterpret_cast(addr), size, 0); return utils::unmap(addr, size); } @@ -871,8 +872,7 @@ bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) { (address & kBlockMask) >> kPageShift, pages, kAllocated | (prot & (kMapProtCpuAll | kMapProtGpuAll))); - // orbis::bridge.sendMemoryProtect(reinterpret_cast(addr), - // size, prot); + rx::bridge.sendMemoryProtect(reinterpret_cast(addr), size, prot); return ::mprotect(addr, size, prot & kMapProtCpuAll) == 0; }