Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Squashing more fastmem stuff #661

Merged
merged 33 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fbddb02
PCSX2 fastmem depression
wheremyfoodat Nov 28, 2024
ede3a93
Move away from PCSX2 fastmem
wheremyfoodat Nov 28, 2024
3f76620
Add enum_flag_ops.hpp
wheremyfoodat Nov 28, 2024
dbc0dfd
Finally building on Windows
wheremyfoodat Nov 28, 2024
798a031
Almost got a PoC
wheremyfoodat Nov 29, 2024
f5b7a6d
Fix arm64 builds
wheremyfoodat Nov 29, 2024
9085b50
This somehow works
wheremyfoodat Nov 30, 2024
ca068c4
This also works...
wheremyfoodat Nov 30, 2024
f4d6299
Properly fix fastmem
wheremyfoodat Nov 30, 2024
e593fb6
Add free region manager
wheremyfoodat Nov 30, 2024
a74ffaf
Update boost
wheremyfoodat Nov 30, 2024
08b09e1
Add ScopeExit
wheremyfoodat Nov 30, 2024
95052ef
Comment out asserts on Linux/Mac/Android
wheremyfoodat Nov 30, 2024
2ced5c1
Comment out ASSERT_MSG asserts too
wheremyfoodat Nov 30, 2024
87cdf0b
Fix derp
wheremyfoodat Nov 30, 2024
8a6bb80
Attempt to fix Android
wheremyfoodat Nov 30, 2024
f422825
Disable fastmem on Android
wheremyfoodat Nov 30, 2024
a576467
Fix Android again maybe pt 2
wheremyfoodat Nov 30, 2024
ec13e1c
android pls
wheremyfoodat Nov 30, 2024
6f71b0e
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
wheremyfoodat Nov 30, 2024
48e277c
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
wheremyfoodat Nov 30, 2024
4ec776f
Update host_memory.cpp
wheremyfoodat Nov 30, 2024
19769e8
Properly reset memory arena on reset
wheremyfoodat Nov 30, 2024
f7dc10b
Merge branch 'master' into fastmem
wheremyfoodat Nov 30, 2024
b98d009
Proper ashmem code for Android
wheremyfoodat Dec 1, 2024
1c0c17a
more
wheremyfoodat Dec 1, 2024
18217e8
Add temporary Android buildjet script for faster prototype builds
wheremyfoodat Dec 1, 2024
5811bc4
Merge branch 'master' into fastmem
wheremyfoodat Dec 2, 2024
57433bb
Merge branch 'master' into fastmem
wheremyfoodat Dec 3, 2024
7dd82a3
Merge branch 'master' into fastmem
wheremyfoodat Dec 3, 2024
080df1b
Fix fastmem (again)
wheremyfoodat Dec 3, 2024
ef056b9
Clean up shared memory
wheremyfoodat Dec 3, 2024
12cbb70
Merge branch 'master' into fastmem
wheremyfoodat Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/Android_Build_Buildjet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Android Build (Buildjet)

on:
push:
branches:
- master
pull_request:

jobs:
arm64:
runs-on: buildjet-32vcpu-ubuntu-2204

strategy:
matrix:
build_type:
- release

steps:
- name: Set BUILD_TYPE variable
run: echo "BUILD_TYPE=${{ matrix.build_type }}" >> $GITHUB_ENV

- uses: actions/checkout@v4
- name: Fetch submodules
run: git submodule update --init --recursive

- name: Set up gradle caches
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-pandroid-arm64-${{ github.sha }}
restore-keys: |
${{ runner.os }}-pandroid-arm64-
- name: Setup Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DBUILD_HYDRA_CORE=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DENABLE_VULKAN=0 -DENABLE_USER_BUILD=ON -DCMAKE_CXX_FLAGS="-march=armv8-a+crypto"

- name: Build
run: |
# Apply patch for GLES compatibility
git apply ./.github/gles.patch
# Build the project with CMake
cmake --build ${{github.workspace}}/build --config RelWithDebInfo
# Strip the generated library and move it to the appropriate location
${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip --strip-unneeded ./build/libAlber.so
mv ./build/libAlber.so ./src/pandroid/app/src/main/jniLibs/arm64-v8a/
# Build the Android app with Gradle
cd src/pandroid
./gradlew assembleDebug
ls -R app/build/outputs
cd ../..
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: Android APKs (arm64)
path: |
./src/pandroid/app/build/outputs/apk/${{ env.BUILD_TYPE }}/app-${{ env.BUILD_TYPE }}.apk
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ option(BUILD_HYDRA_CORE "Build a Hydra core" OFF)
option(BUILD_LIBRETRO_CORE "Build a Libretro core" OFF)
option(ENABLE_RENDERDOC_API "Build with support for Renderdoc's capture API for graphics debugging" ON)
option(DISABLE_SSE4 "Build with SSE4 instructions disabled, may reduce performance" OFF)
option(ENABLE_FASTMEM "Build with support for hardware fastmem" ON)

set(OPENGL_PROFILE ${DEFAULT_OPENGL_PROFILE} CACHE STRING "OpenGL profile to use if OpenGL is enabled. Valid values are 'OpenGL' and 'OpenGLES'.")
set_property(CACHE OPENGL_PROFILE PROPERTY STRINGS OpenGL OpenGLES)
Expand Down Expand Up @@ -165,6 +166,7 @@ include_directories(third_party/toml11)
include_directories(third_party/glm)
include_directories(third_party/renderdoc)
include_directories(third_party/duckstation)
include_directories(third_party/host_memory/include)

add_subdirectory(third_party/cmrc)

Expand Down Expand Up @@ -280,7 +282,7 @@ set(SOURCE_FILES src/emulator.cpp src/io_file.cpp src/config.cpp
src/core/memory.cpp src/renderer.cpp src/core/renderer_null/renderer_null.cpp
src/http_server.cpp src/stb_image_write.c src/core/cheats.cpp src/core/action_replay.cpp
src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp src/miniaudio.cpp src/renderdoc.cpp
src/frontend_settings.cpp
src/frontend_settings.cpp src/dynamic_library.cpp
)
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
set(KERNEL_SOURCE_FILES src/core/kernel/kernel.cpp src/core/kernel/resource_limits.cpp
Expand Down Expand Up @@ -362,7 +364,8 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/PICA/pica_vert_config.hpp include/sdl_sensors.hpp include/PICA/draw_acceleration.hpp include/renderdoc.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp
include/services/dsp_firmware_db.hpp include/frontend_settings.hpp
include/enum_flag_ops.hpp include/services/dsp_firmware_db.hpp include/frontend_settings.hpp
include/dynamic_library.hpp
)

cmrc_add_resource_library(
Expand All @@ -380,6 +383,9 @@ set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp

third_party/cityhash/cityhash.cpp
third_party/xxhash/xxhash.c

third_party/host_memory/host_memory.cpp
third_party/host_memory/virtual_buffer.cpp
)

if(ENABLE_LUAJIT AND NOT ANDROID)
Expand Down Expand Up @@ -625,6 +631,10 @@ if(ENABLE_HTTP_SERVER)
target_compile_definitions(AlberCore PRIVATE PANDA3DS_ENABLE_HTTP_SERVER=1)
endif()

if(ENABLE_FASTMEM)
target_compile_definitions(AlberCore PRIVATE PANDA3DS_HARDWARE_FASTMEM=1)
endif()

# Configure frontend

if(ENABLE_QT_GUI)
Expand Down
73 changes: 73 additions & 0 deletions include/dynamic_library.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2019 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <string>

namespace Common {
/**
* Provides a platform-independent interface for loading a dynamic library and retrieving symbols.
* The interface maintains an internal reference count to allow one handle to be shared between
* multiple users.
*/
class DynamicLibrary final {
public:
/// Default constructor, does not load a library.
explicit DynamicLibrary();

/// Automatically loads the specified library. Call IsOpen() to check validity before use.
explicit DynamicLibrary(const char* filename);

/// Initializes the dynamic library with an already opened handle.
explicit DynamicLibrary(void* handle_);

/// Moves the library.
DynamicLibrary(DynamicLibrary&&) noexcept;
DynamicLibrary& operator=(DynamicLibrary&&) noexcept;

/// Delete copies, we can't copy a dynamic library.
DynamicLibrary(const DynamicLibrary&) = delete;
DynamicLibrary& operator=(const DynamicLibrary&) = delete;

/// Closes the library.
~DynamicLibrary();

/// Returns the specified library name with the platform-specific suffix added.
[[nodiscard]] static std::string getUnprefixedFilename(const char* filename);

/// Returns the specified library name in platform-specific format.
/// Major/minor versions will not be included if set to -1.
/// If libname already contains the "lib" prefix, it will not be added again.
/// Windows: LIBNAME-MAJOR-MINOR.dll
/// Linux: libLIBNAME.so.MAJOR.MINOR
/// Mac: libLIBNAME.MAJOR.MINOR.dylib
[[nodiscard]] static std::string getVersionedFilename(const char* libname, int major = -1, int minor = -1);

/// Returns true if a module is loaded, otherwise false.
[[nodiscard]] bool isOpen() const { return handle != nullptr; }

/// Loads (or replaces) the handle with the specified library file name.
/// Returns true if the library was loaded and can be used.
[[nodiscard]] bool open(const char* filename);

/// Unloads the library, any function pointers from this library are no longer valid.
void close();

/// Returns the address of the specified symbol (function or variable) as an untyped pointer.
/// If the specified symbol does not exist in this library, nullptr is returned.
[[nodiscard]] void* getSymbolAddress(const char* name) const;

/// Obtains the address of the specified symbol, automatically casting to the correct type.
/// Returns true if the symbol was found and assigned, otherwise false.
template <typename T>
[[nodiscard]] bool getSymbol(const char* name, T* ptr) const {
*ptr = reinterpret_cast<T>(getSymbolAddress(name));
return *ptr != nullptr;
}

private:
/// Platform-dependent data type representing a dynamic library handle.
void* handle = nullptr;
};
} // namespace Common
4 changes: 2 additions & 2 deletions include/emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ enum class ROMType {

class Emulator {
EmulatorConfig config;
Memory memory;
CPU cpu;
GPU gpu;
Memory memory;
Kernel kernel;
std::unique_ptr<Audio::DSPCore> dsp;
Scheduler scheduler;
Expand All @@ -55,7 +55,7 @@ class Emulator {
static constexpr u32 width = 400;
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
ROMType romType = ROMType::None;
bool running = false; // Is the emulator running a game?
bool running = false; // Is the emulator running a game?

private:
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
Expand Down
60 changes: 60 additions & 0 deletions include/enum_flag_ops.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <type_traits>

#define DECLARE_ENUM_FLAG_OPERATORS(type) \
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator&(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator^(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) ^ static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator<<(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) << static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator>>(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) >> static_cast<T>(b)); \
} \
constexpr type& operator|=(type& a, type b) noexcept { \
a = a | b; \
return a; \
} \
constexpr type& operator&=(type& a, type b) noexcept { \
a = a & b; \
return a; \
} \
constexpr type& operator^=(type& a, type b) noexcept { \
a = a ^ b; \
return a; \
} \
constexpr type& operator<<=(type& a, type b) noexcept { \
a = a << b; \
return a; \
} \
constexpr type& operator>>=(type& a, type b) noexcept { \
a = a >> b; \
return a; \
} \
[[nodiscard]] constexpr type operator~(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(~static_cast<T>(key)); \
} \
[[nodiscard]] constexpr bool True(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) != 0; \
} \
[[nodiscard]] constexpr bool False(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) == 0; \
}
42 changes: 39 additions & 3 deletions include/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
#include <bitset>
#include <filesystem>
#include <fstream>
#include <memory>
#include <optional>
#include <vector>

#include "config.hpp"
#include "crypto/aes_engine.hpp"
#include "handles.hpp"
#include "helpers.hpp"
#include "loader/ncsd.hpp"
#include "host_memory/host_memory.h"
#include "loader/3dsx.hpp"
#include "loader/ncsd.hpp"
#include "services/region_codes.hpp"

namespace PhysicalAddrs {
Expand Down Expand Up @@ -108,7 +110,7 @@ class Memory {
u8* dspRam; // Provided to us by Audio
u8* vram; // Provided to the memory class by the GPU class

u64& cpuTicks; // Reference to the CPU tick counter
const u64* cpuTicks = nullptr; // Pointer to the CPU tick counter, provided to us by the CPU class
using SharedMemoryBlock = KernelMemoryTypes::SharedMemoryBlock;

// Our dynarmic core uses page tables for reads and writes with 4096 byte pages
Expand Down Expand Up @@ -141,6 +143,36 @@ class Memory {
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);

private:
// We also use MMU-accelerated fastmem for fast memory emulation
// This means that we've got a 4GB memory arena which is organized the same way as the emulated 3DS' memory map
// And we can access this directly instead of calling the memory read/write functions, which would be slower
// Regions that are not mapped or can't be accelerated this way will segfault, and the caller (eg dynarmic), will
// handle this segfault and call the Slower memory read/write functions
bool useFastmem = false;
static constexpr size_t FASTMEM_FCRAM_OFFSET = 0; // Offset of FCRAM in the fastmem arena
static constexpr size_t FASTMEM_DSP_RAM_OFFSET = FASTMEM_FCRAM_OFFSET + FCRAM_SIZE; // Offset of DSP RAM

static constexpr size_t FASTMEM_BACKING_SIZE = FCRAM_SIZE + DSP_RAM_SIZE;
// Total size of the virtual address space we will occupy (4GB)
static constexpr size_t FASTMEM_VIRTUAL_SIZE = 4_GB;

Common::HostMemory* arena;

void addFastmemView(u32 guestVaddr, size_t arenaOffset, size_t size, bool w, bool x = false) {
if (useFastmem) {
Common::MemoryPermission perms = Common::MemoryPermission::Read;
if (w) {
perms |= Common::MemoryPermission::Write;
}

if (x) {
//perms |= Common::MemoryPermission::Execute;
}

arena->Map(guestVaddr, arenaOffset, size, perms, false);
}
}

std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
std::optional<u32> findPaddr(u32 size);
u64 timeSince3DSEpoch();
Expand Down Expand Up @@ -172,7 +204,7 @@ class Memory {
u32 usedUserMemory = u32(0_MB); // How much of the APPLICATION FCRAM range is used (allocated to the appcore)
u32 usedSystemMemory = u32(0_MB); // Similar for the SYSTEM range (reserved for the syscore)

Memory(u64& cpuTicks, const EmulatorConfig& config);
Memory(const EmulatorConfig& config);
void reset();
void* getReadPointer(u32 address);
void* getWritePointer(u32 address);
Expand Down Expand Up @@ -295,8 +327,12 @@ class Memory {

void setVRAM(u8* pointer) { vram = pointer; }
void setDSPMem(u8* pointer) { dspRam = pointer; }
void setCPUTicks(const u64& ticks) { cpuTicks = &ticks; }

bool allocateMainThreadStack(u32 size);
Regions getConsoleRegion();
void copySharedFont(u8* ptr, u32 vaddr);

bool isFastmemEnabled() { return useFastmem; }
u8* getFastmemArenaBase() { return arena->VirtualBasePointer(); }
};
7 changes: 7 additions & 0 deletions src/core/CPU/cpu_dynarmic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

CPU::CPU(Memory& mem, Kernel& kernel, Emulator& emu) : mem(mem), emu(emu), scheduler(emu.getScheduler()), env(mem, kernel, emu.getScheduler()) {
cp15 = std::make_shared<CP15>();
mem.setCPUTicks(getTicksRef());

Dynarmic::A32::UserConfig config;
config.arch_version = Dynarmic::A32::ArchVersion::v6K;
Expand All @@ -15,6 +16,12 @@ CPU::CPU(Memory& mem, Kernel& kernel, Emulator& emu) : mem(mem), emu(emu), sched
config.global_monitor = &exclusiveMonitor;
config.processor_id = 0;

if (mem.isFastmemEnabled()) {
config.fastmem_pointer = u64(mem.getFastmemArenaBase());
} else {
config.fastmem_pointer = std::nullopt;
}

jit = std::make_unique<Dynarmic::A32::Jit>(config);
}

Expand Down
Loading
Loading