mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-24 20:35:01 +00:00
video_core: Rewrite vulkan and videoout
This commit is contained in:
parent
0a94899c86
commit
c01b6f8397
89 changed files with 5378 additions and 2150 deletions
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "core/libraries/kernel/event_queue.h"
|
||||
|
||||
|
@ -11,16 +12,11 @@ EqueueInternal::~EqueueInternal() = default;
|
|||
int EqueueInternal::addEvent(const EqueueEvent& event) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
|
||||
if (m_events.size() > 0) {
|
||||
BREAKPOINT();
|
||||
}
|
||||
ASSERT(m_events.empty());
|
||||
ASSERT(!event.isTriggered);
|
||||
|
||||
// TODO check if event is already exists and return it. Currently we just add in m_events array
|
||||
m_events.push_back(event);
|
||||
|
||||
if (event.isTriggered) {
|
||||
BREAKPOINT(); // we don't support that either yet
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -33,28 +29,26 @@ int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
|||
return ret > 0;
|
||||
};
|
||||
|
||||
char buf[128];
|
||||
pthread_getname_np(pthread_self(), buf, 128);
|
||||
fmt::print("Thread {} waiting for events (micros = {})\n", buf, micros);
|
||||
|
||||
if (micros == 0) {
|
||||
m_cond.wait(lock, predicate);
|
||||
} else {
|
||||
m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate);
|
||||
}
|
||||
fmt::print("Wait done\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
|
||||
if (m_events.size() > 1) {
|
||||
BREAKPOINT(); // we currently support one event
|
||||
}
|
||||
ASSERT(m_events.size() <= 1);
|
||||
|
||||
auto& event = m_events[0];
|
||||
|
||||
if (event.filter.trigger_event_func != nullptr) {
|
||||
event.filter.trigger_event_func(&event, trigger_data);
|
||||
} else {
|
||||
event.isTriggered = true;
|
||||
}
|
||||
|
||||
event.trigger(trigger_data);
|
||||
m_cond.notify_one();
|
||||
|
||||
return true;
|
||||
|
@ -63,17 +57,12 @@ bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
|||
int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) {
|
||||
int ret = 0;
|
||||
|
||||
if (m_events.size() > 1) {
|
||||
BREAKPOINT(); // we currently support one event
|
||||
}
|
||||
ASSERT(m_events.size() <= 1);
|
||||
auto& event = m_events[0];
|
||||
|
||||
if (event.isTriggered) {
|
||||
ev[ret++] = event.event;
|
||||
|
||||
if (event.filter.reset_event_func != nullptr) {
|
||||
event.filter.reset_event_func(&event);
|
||||
}
|
||||
event.reset();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -52,15 +52,24 @@ struct SceKernelEvent {
|
|||
|
||||
struct Filter {
|
||||
void* data = nullptr;
|
||||
TriggerFunc trigger_event_func = nullptr;
|
||||
ResetFunc reset_event_func = nullptr;
|
||||
DeleteFunc delete_event_func = nullptr;
|
||||
};
|
||||
|
||||
struct EqueueEvent {
|
||||
bool isTriggered = false;
|
||||
SceKernelEvent event;
|
||||
Filter filter;
|
||||
|
||||
void reset() {
|
||||
isTriggered = false;
|
||||
event.fflags = 0;
|
||||
event.data = 0;
|
||||
}
|
||||
|
||||
void trigger(void* data) {
|
||||
isTriggered = true;
|
||||
event.fflags++;
|
||||
event.data = reinterpret_cast<uintptr_t>(data);
|
||||
}
|
||||
};
|
||||
|
||||
class EqueueInternal {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <bit>
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/PS4/GPU/gpu_memory.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/memory_management.h"
|
||||
#include "core/libraries/kernel/physical_memory.h"
|
||||
|
@ -13,10 +13,6 @@
|
|||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
bool is16KBAligned(u64 n) {
|
||||
return ((n % (16ull * 1024) == 0));
|
||||
}
|
||||
|
||||
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
|
||||
LOG_WARNING(Kernel_Vmm, "called");
|
||||
return SCE_KERNEL_MAIN_DMEM_SIZE;
|
||||
|
@ -34,11 +30,11 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
const bool is_in_range = (searchStart < len && searchEnd > len);
|
||||
if (len <= 0 || !is16KBAligned(len) || !is_in_range) {
|
||||
if (len <= 0 || !Common::is16KBAligned(len) || !is_in_range) {
|
||||
LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if ((alignment != 0 || is16KBAligned(alignment)) && !std::has_single_bit(alignment)) {
|
||||
if ((alignment != 0 || Common::is16KBAligned(alignment)) && !std::has_single_bit(alignment)) {
|
||||
LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
@ -66,23 +62,22 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
|
|||
"len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = {:#x}",
|
||||
len, prot, flags, directMemoryStart, alignment);
|
||||
|
||||
if (len == 0 || !is16KBAligned(len)) {
|
||||
if (len == 0 || !Common::is16KBAligned(len)) {
|
||||
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (!is16KBAligned(directMemoryStart)) {
|
||||
if (!Common::is16KBAligned(directMemoryStart)) {
|
||||
LOG_ERROR(Kernel_Vmm, "Start address is not 16KB aligned!");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (alignment != 0) {
|
||||
if ((!std::has_single_bit(alignment) && !is16KBAligned(alignment))) {
|
||||
if ((!std::has_single_bit(alignment) && !Common::is16KBAligned(alignment))) {
|
||||
LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess;
|
||||
GPU::MemoryMode gpu_mode = GPU::MemoryMode::NoAccess;
|
||||
|
||||
switch (prot) {
|
||||
case 0x03:
|
||||
|
@ -91,7 +86,6 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
|
|||
case 0x32:
|
||||
case 0x33: // SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL
|
||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||
gpu_mode = GPU::MemoryMode::ReadWrite;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -112,13 +106,10 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
|
|||
}
|
||||
|
||||
auto* physical_memory = Common::Singleton<PhysicalMemory>::Instance();
|
||||
if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode, gpu_mode)) {
|
||||
if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (gpu_mode != GPU::MemoryMode::NoAccess) {
|
||||
GPU::memorySetAllocArea(out_addr, len);
|
||||
}
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "core/libraries/kernel/physical_memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
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) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
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
|
||||
for (const auto& block : m_allocatedBlocks) {
|
||||
u64 n = block.start_addr + block.size;
|
||||
if (n > find_free_pos) {
|
||||
|
@ -22,16 +19,15 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
|
|||
}
|
||||
}
|
||||
|
||||
// align free position
|
||||
find_free_pos = AlignUp(find_free_pos, alignment);
|
||||
// Align free position
|
||||
find_free_pos = Common::alignUp(find_free_pos, alignment);
|
||||
|
||||
// if the new position is between searchStart - searchEnd , allocate a new block
|
||||
// If the new position is between searchStart - searchEnd , allocate a new block
|
||||
if (find_free_pos >= searchStart && find_free_pos + len <= searchEnd) {
|
||||
AllocatedBlock block{};
|
||||
block.size = len;
|
||||
block.start_addr = find_free_pos;
|
||||
block.memoryType = memoryType;
|
||||
block.gpu_mode = GPU::MemoryMode::NoAccess;
|
||||
block.map_size = 0;
|
||||
block.map_virtual_addr = 0;
|
||||
block.prot = 0;
|
||||
|
@ -47,7 +43,7 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
|
|||
}
|
||||
|
||||
bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot,
|
||||
VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode) {
|
||||
VirtualMemory::MemoryMode cpu_mode) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
for (auto& b : m_allocatedBlocks) {
|
||||
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) {
|
||||
|
@ -59,7 +55,6 @@ bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot,
|
|||
b.map_size = len;
|
||||
b.prot = prot;
|
||||
b.cpu_mode = cpu_mode;
|
||||
b.gpu_mode = gpu_mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "core/PS4/GPU/gpu_memory.h"
|
||||
#include "core/virtual_memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
@ -21,7 +20,6 @@ public:
|
|||
u64 map_size;
|
||||
int prot;
|
||||
VirtualMemory::MemoryMode cpu_mode;
|
||||
GPU::MemoryMode gpu_mode;
|
||||
};
|
||||
PhysicalMemory() {}
|
||||
virtual ~PhysicalMemory() {}
|
||||
|
@ -29,8 +27,8 @@ public:
|
|||
public:
|
||||
bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut,
|
||||
int memoryType);
|
||||
bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode,
|
||||
GPU::MemoryMode gpu_mode);
|
||||
bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot,
|
||||
VirtualMemory::MemoryMode cpu_mode);
|
||||
|
||||
private:
|
||||
std::vector<AllocatedBlock> m_allocatedBlocks;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue