diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index ceafa7ba..409b453b 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -113,7 +113,8 @@ struct AddressSpace::Impl { return ptr; } - void* MapPrivate(VAddr virtual_addr, size_t size, u64 alignment, ULONG prot) { + void* MapPrivate(VAddr virtual_addr, size_t size, u64 alignment, ULONG prot, + bool no_commit = false) { // Map a private allocation MEM_ADDRESS_REQUIREMENTS req{}; MEM_EXTENDED_PARAMETER param{}; @@ -124,8 +125,12 @@ struct AddressSpace::Impl { req.Alignment = alignment < 64_KB ? 0 : alignment; param.Type = MemExtendedParameterAddressRequirements; param.Pointer = &req; - ULONG alloc_type = MEM_COMMIT | MEM_RESERVE | (alignment > 2_MB ? MEM_LARGE_PAGES : 0); - void* const ptr = VirtualAlloc2(process, nullptr, size, alloc_type, prot, ¶m, 1); + ULONG alloc_type = MEM_RESERVE | (alignment > 2_MB ? MEM_LARGE_PAGES : 0); + if (!no_commit) { + alloc_type |= MEM_COMMIT; + } + void* const ptr = VirtualAlloc2(process, reinterpret_cast(virtual_addr), size, + alloc_type, prot, ¶m, 1); ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg()); return ptr; } @@ -224,7 +229,8 @@ struct AddressSpace::Impl { return nullptr; } - void* MapPrivate(VAddr virtual_addr, size_t size, u64 alignment, PosixPageProtection prot) { + void* MapPrivate(VAddr virtual_addr, size_t size, u64 alignment, PosixPageProtection prot, + bool no_commit = false) { UNREACHABLE(); return nullptr; } @@ -271,4 +277,8 @@ void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission per return impl->Protect(virtual_addr, size, true, true, true); } +void* AddressSpace::Reserve(size_t size, u64 alignment) { + return impl->MapPrivate(0, size, alignment, PAGE_READWRITE, true); +} + } // namespace Core diff --git a/src/core/address_space.h b/src/core/address_space.h index 322ab9c7..0e344358 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -49,6 +49,8 @@ public: void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms); + void* Reserve(size_t size, u64 alignment); + private: struct Impl; std::unique_ptr impl; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 386446f7..f6550b18 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -10,6 +10,7 @@ #include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/libs.h" #include "core/libraries/videoout/video_out.h" +#include "core/memory.h" #include "core/platform.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/pm4_cmds.h" @@ -40,6 +41,10 @@ struct AscQueueInfo { }; static VideoCore::SlotVector asc_queues{}; +static constexpr u32 TessellationFactorRingSize = 128_KB; +static constexpr u32 TessellationFactorRingAlignment = 64_KB; // toolkit is using this alignment +VAddr tessellation_factors_ring_addr{0}; + static void DumpCommandList(std::span cmd_list, const std::string& postfix) { using namespace Common::FS; const auto dump_dir = GetUserPath(PathType::PM4Dir); @@ -607,9 +612,15 @@ int PS4_SYSV_ABI sceGnmGetShaderStatus() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmGetTheTessellationFactorRingBufferBaseAddress() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +VAddr PS4_SYSV_ABI sceGnmGetTheTessellationFactorRingBufferBaseAddress() { + LOG_TRACE(Lib_GnmDriver, "called"); + // Actual virtual buffer address is hardcoded in the driver to 0xff00'000 + if (tessellation_factors_ring_addr == 0) { + auto* memory = Core::Memory::Instance(); + tessellation_factors_ring_addr = + memory->Reserve(TessellationFactorRingSize, TessellationFactorRingAlignment); + } + return tessellation_factors_ring_addr; } int PS4_SYSV_ABI sceGnmGpuPaDebugEnter() { diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 4319d0dc..b2e78436 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -97,7 +97,7 @@ int PS4_SYSV_ABI sceGnmGetResourceType(); int PS4_SYSV_ABI sceGnmGetResourceUserData(); int PS4_SYSV_ABI sceGnmGetShaderProgramBaseAddress(); int PS4_SYSV_ABI sceGnmGetShaderStatus(); -int PS4_SYSV_ABI sceGnmGetTheTessellationFactorRingBufferBaseAddress(); +VAddr PS4_SYSV_ABI sceGnmGetTheTessellationFactorRingBufferBaseAddress(); int PS4_SYSV_ABI sceGnmGpuPaDebugEnter(); int PS4_SYSV_ABI sceGnmGpuPaDebugLeave(); int PS4_SYSV_ABI sceGnmInsertDingDongMarker(); diff --git a/src/core/memory.h b/src/core/memory.h index 7a623db7..87cd9188 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -115,6 +115,10 @@ public: int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info); + VAddr Reserve(size_t size, u64 alignment) { + return reinterpret_cast(impl.Reserve(size, alignment)); + } + std::pair GetVulkanBuffer(VAddr addr); private: