From 52edef0867a7145b107cf9eee99f9f495416c2fa Mon Sep 17 00:00:00 2001
From: Elad <18193363+elad335@users.noreply.github.com>
Date: Fri, 14 Feb 2025 16:59:16 +0200
Subject: [PATCH] Remove xxHash submodule
---
.gitmodules | 4 -
3rdparty/CMakeLists.txt | 14 ----
3rdparty/xxHash | 1 -
3rdparty/xxhash.vcxproj | 65 ---------------
buildfiles/msvc/rpcs3_default.props | 4 +-
rpcs3.sln | 8 --
rpcs3/Emu/CMakeLists.txt | 2 +-
rpcs3/Emu/RSX/Capture/rsx_capture.cpp | 71 ++++++++++-------
rpcs3/Emu/RSX/Capture/rsx_replay.cpp | 17 ++--
rpcs3/Emu/RSX/Capture/rsx_replay.h | 61 +++++++++++---
rpcs3/util/serialization.hpp | 109 ++++++++++++++++++++------
11 files changed, 187 insertions(+), 169 deletions(-)
delete mode 160000 3rdparty/xxHash
delete mode 100644 3rdparty/xxhash.vcxproj
diff --git a/.gitmodules b/.gitmodules
index 50cdb67ab6..9f453de899 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,10 +28,6 @@
path = 3rdparty/pugixml
url = ../../zeux/pugixml.git
ignore = dirty
-[submodule "3rdparty/xxHash"]
- path = 3rdparty/xxHash
- url = ../../Cyan4973/xxHash.git
- ignore = dirty
[submodule "3rdparty/yaml-cpp"]
path = 3rdparty/yaml-cpp/yaml-cpp
url = ../../RPCS3/yaml-cpp.git
diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
index 4c2c6a35ac..4625c0e81e 100644
--- a/3rdparty/CMakeLists.txt
+++ b/3rdparty/CMakeLists.txt
@@ -97,19 +97,6 @@ target_link_libraries(3rdparty_glslang INTERFACE SPIRV)
add_subdirectory(yaml-cpp)
-# xxHash
-if (USE_SYSTEM_XXHASH)
- pkg_check_modules(XXHASH REQUIRED IMPORTED_TARGET libxxhash)
- add_library(xxhash INTERFACE)
- target_link_libraries(xxhash INTERFACE PkgConfig::XXHASH)
-else()
- set(XXHASH_BUNDLED_MODE ON)
- set(XXHASH_BUILD_XXHSUM OFF)
- set(BUILD_SHARED_LIBS OFF CACHE BOOL "Make xxHash build static libs")
- add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL)
- target_include_directories(xxhash INTERFACE xxHash)
-endif()
-
# OpenGL
find_package(OpenGL REQUIRED OPTIONAL_COMPONENTS EGL)
@@ -364,7 +351,6 @@ add_library(3rdparty::flatbuffers ALIAS 3rdparty_flatbuffers)
add_library(3rdparty::pugixml ALIAS pugixml)
add_library(3rdparty::glslang ALIAS 3rdparty_glslang)
add_library(3rdparty::yaml-cpp ALIAS yaml-cpp)
-add_library(3rdparty::xxhash ALIAS xxhash)
add_library(3rdparty::hidapi ALIAS 3rdparty_hidapi)
add_library(3rdparty::libpng ALIAS ${LIBPNG_TARGET})
add_library(3rdparty::opengl ALIAS 3rdparty_opengl)
diff --git a/3rdparty/xxHash b/3rdparty/xxHash
deleted file mode 160000
index e626a72bc2..0000000000
--- a/3rdparty/xxHash
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e626a72bc2321cd320e953a0ccf1584cad60f363
diff --git a/3rdparty/xxhash.vcxproj b/3rdparty/xxhash.vcxproj
deleted file mode 100644
index 6985e3205a..0000000000
--- a/3rdparty/xxhash.vcxproj
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- {939FE206-1182-ABC3-1234-FEAB88E98404}
-
-
-
-
-
- StaticLibrary
- Unicode
-
-
- true
-
-
- false
-
-
-
- x64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- MaxSpeed
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/buildfiles/msvc/rpcs3_default.props b/buildfiles/msvc/rpcs3_default.props
index 77aca3d0dd..4f5862ca84 100644
--- a/buildfiles/msvc/rpcs3_default.props
+++ b/buildfiles/msvc/rpcs3_default.props
@@ -3,7 +3,7 @@
- .\;..\;..\3rdparty\asmjit\asmjit\src;..\..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\libpng\libpng;..\3rdparty\GL;..\3rdparty\stblib\stb;..\3rdparty\openal\openal-soft\include\AL;..\3rdparty\pugixml\src;..\3rdparty\hidapi\hidapi;..\3rdparty\Optional;..\3rdparty\xxhash
+ .\;..\;..\3rdparty\asmjit\asmjit\src;..\..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\libpng\libpng;..\3rdparty\GL;..\3rdparty\stblib\stb;..\3rdparty\openal\openal-soft\include\AL;..\3rdparty\pugixml\src;..\3rdparty\hidapi\hidapi
$(SolutionDir)build\lib\$(Configuration)-$(Platform)\
$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)
$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\
@@ -23,7 +23,7 @@
/utf-8 /Zc:throwingNew- /constexpr:steps16777216 %(AdditionalOptions)
- xxhash.lib;ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib
+ ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib
..\3rdparty\ffmpeg\lib\windows\x86_64
8388608
1048576
diff --git a/rpcs3.sln b/rpcs3.sln
index 26bc66179b..4b920a68e0 100644
--- a/rpcs3.sln
+++ b/rpcs3.sln
@@ -10,7 +10,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vc
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
{5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0} = {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {8846A9AA-5539-4C91-8301-F54260E1A07A}
- {939FE206-1182-ABC3-1234-FEAB88E98404} = {939FE206-1182-ABC3-1234-FEAB88E98404}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llvm_build", "3rdparty\llvm\llvm_build.vcxproj", "{8BC303AB-25BE-4276-8E57-73F171B2D672}"
@@ -67,8 +66,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "3rdparty\hidapi\hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xxhash", "3rdparty\xxhash.vcxproj", "{939FE206-1182-ABC3-1234-FEAB88E98404}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "3rdparty\libusb\libusb_static.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "3rdparty\wolfssl\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}"
@@ -161,10 +158,6 @@ Global
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
- {939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.ActiveCfg = Debug|x64
- {939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.Build.0 = Debug|x64
- {939FE206-1182-ABC3-1234-FEAB88E98404}.Release|x64.ActiveCfg = Release|x64
- {939FE206-1182-ABC3-1234-FEAB88E98404}.Release|x64.Build.0 = Release|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
@@ -236,7 +229,6 @@ Global
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{FDC361C5-7734-493B-8CFB-037308B35122} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
- {939FE206-1182-ABC3-1234-FEAB88E98404} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{73973223-5EE8-41CA-8E88-1D60E89A237B} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index 0b78942ac9..cd4cdb2a46 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -641,7 +641,7 @@ target_link_libraries(rpcs3_emu
3rdparty::vulkan 3rdparty::glew
3rdparty::libusb 3rdparty::wolfssl
PRIVATE
- 3rdparty::glslang 3rdparty::xxhash
+ 3rdparty::glslang
)
if(APPLE)
diff --git a/rpcs3/Emu/RSX/Capture/rsx_capture.cpp b/rpcs3/Emu/RSX/Capture/rsx_capture.cpp
index bfd47df73d..3ac2dd929e 100644
--- a/rpcs3/Emu/RSX/Capture/rsx_capture.cpp
+++ b/rpcs3/Emu/RSX/Capture/rsx_capture.cpp
@@ -6,33 +6,33 @@
#include "Emu/RSX/RSXThread.h"
#include "Emu/Memory/vm.h"
-#include "xxhash.h"
-
namespace rsx
{
namespace capture
{
- void insert_mem_block_in_map(std::unordered_set& mem_changes, frame_capture_data::memory_block&& block, frame_capture_data::memory_block_data&& data)
+ void insert_mem_block_in_map(u64& indexer, std::unordered_set& mem_changes, frame_capture_data::memory_block&& block, frame_capture_data::memory_block_data&& data)
{
if (!data.data.empty())
{
- u64 data_hash = XXH64(data.data.data(), data.data.size(), 0);
+ const auto [it, inserted] = frame_capture.memory_data_map.try_emplace(data, 0);
+ u64& data_hash = it->second;
+
+ if (inserted)
+ {
+ data_hash = ++indexer;
+ }
+
block.data_state = data_hash;
- auto it = frame_capture.memory_data_map.find(data_hash);
- if (it != frame_capture.memory_data_map.end())
- {
- if (it->second.data != data.data)
- // screw this
- fmt::throw_exception("Memory map hash collision detected...cant capture");
- }
- else
- frame_capture.memory_data_map.insert(std::make_pair(data_hash, std::move(data)));
+ const auto [block_it, inserted_block] = frame_capture.memory_map.try_emplace(block, 0);
+ u64& block_hash = block_it->second;
+
+ if (inserted_block)
+ {
+ block_hash = ++indexer;
+ }
- u64 block_hash = XXH64(&block, sizeof(frame_capture_data::memory_block), 0);
mem_changes.insert(block_hash);
- if (frame_capture.memory_map.find(block_hash) == frame_capture.memory_map.end())
- frame_capture.memory_map.insert(std::make_pair(block_hash, std::move(block)));
}
}
@@ -48,6 +48,7 @@ namespace rsx
// shove the mem_changes onto the last issued command
std::unordered_set& mem_changes = frame_capture.replay_commands.back().memory_state;
+ u64& mem_indexer = frame_capture.memory_indexer;
// capture fragment shader mem
const auto [program_offset, program_location] = method_registers.shader_program_address();
@@ -63,7 +64,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(ucode_size + program_start);
std::memcpy(block_data.data.data(), vm::base(addr), ucode_size + program_start);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
// vertex shader is passed in registers, so it can be ignored
@@ -90,7 +91,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(texSize);
std::memcpy(block_data.data.data(), vm::base(texaddr), texSize);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
}
// save vertex texture mem
@@ -116,7 +117,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(texSize);
std::memcpy(block_data.data.data(), vm::base(texaddr), texSize);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
}
// save vertex buffer memory
@@ -154,7 +155,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(bufferSize);
std::memcpy(block_data.data.data(), vm::base(addr + (range.first * vertStride)), bufferSize);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
}
while (method_registers.current_draw_clause.next());
}
@@ -193,7 +194,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(bufferSize);
std::memcpy(block_data.data.data(), vm::base(idxAddr), bufferSize);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
switch (index_type)
{
@@ -256,7 +257,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(bufferSize);
std::memcpy(block_data.data.data(), vm::base(addr + (min_index * vertStride)), bufferSize);
- insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
}
}
}
@@ -308,7 +309,7 @@ namespace rsx
frame_capture_data::memory_block_data block_data;
block_data.data.resize(src_size);
std::memcpy(block_data.data.data(), pixels_src, src_size);
- insert_mem_block_in_map(replay_command.memory_state, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(frame_capture.memory_indexer, replay_command.memory_state, std::move(block), std::move(block_data));
capture_display_tile_state(rsx, replay_command);
}
@@ -340,14 +341,17 @@ namespace rsx
src += in_pitch;
}
- insert_mem_block_in_map(replay_command.memory_state, std::move(block), std::move(block_data));
+ insert_mem_block_in_map(frame_capture.memory_indexer, replay_command.memory_state, std::move(block), std::move(block_data));
capture_display_tile_state(rsx, replay_command);
}
void capture_display_tile_state(thread* rsx, frame_capture_data::replay_command& replay_command)
{
+ u64& mem_indexer = frame_capture.memory_indexer;
+
frame_capture_data::display_buffers_state dbstate;
dbstate.count = rsx->display_buffers_count;
+
// should this only happen on flip?
for (u32 i = 0; i < rsx->display_buffers_count; ++i)
{
@@ -358,9 +362,13 @@ namespace rsx
dbstate.buffers[i].pitch = db.pitch;
}
- const u64 dbnum = XXH64(&dbstate, sizeof(frame_capture_data::display_buffers_state), 0);
- if (frame_capture.display_buffers_map.find(dbnum) == frame_capture.display_buffers_map.end())
- frame_capture.display_buffers_map.insert(std::make_pair(dbnum, std::move(dbstate)));
+ const auto [db_it, db_inserted] = frame_capture.display_buffers_map.try_emplace(dbstate, 0);
+ u64& dbnum = db_it->second;
+
+ if (db_inserted)
+ {
+ dbnum = ++mem_indexer;
+ }
// todo: hook tile call sys_rsx call or something
frame_capture_data::tile_state tilestate;
@@ -386,10 +394,13 @@ namespace rsx
zcstate.status1 = rsx->zculls[i].bound ? u32{zc.status1} : 0;
}
- const u64 tsnum = XXH64(&tilestate, sizeof(frame_capture_data::tile_state), 0);
+ const auto [ts_it, ts_inserted] = frame_capture.tile_map.try_emplace(tilestate, 0);
+ u64& tsnum = ts_it->second;
- if (frame_capture.tile_map.find(tsnum) == frame_capture.tile_map.end())
- frame_capture.tile_map.insert(std::make_pair(tsnum, std::move(tilestate)));
+ if (ts_inserted)
+ {
+ tsnum = ++mem_indexer;
+ }
replay_command.display_buffer_state = dbnum;
replay_command.tile_state = tsnum;
diff --git a/rpcs3/Emu/RSX/Capture/rsx_replay.cpp b/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
index 88bd6f9028..bb558744aa 100644
--- a/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
+++ b/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
@@ -106,26 +106,26 @@ namespace rsx
// apply memory needed for command
for (const auto& state : replay_cmd.memory_state)
{
- auto it = frame->memory_map.find(state);
+ auto it = std::find_if(frame->memory_map.begin(), frame->memory_map.end(), FN(x.second == state));
if (it == frame->memory_map.end())
fmt::throw_exception("requested memory state for command not found in memory_map");
- const auto& memblock = it->second;
- auto it_data = frame->memory_data_map.find(it->second.data_state);
+ const auto& memblock = it->first;
+ auto it_data = std::find_if(frame->memory_data_map.begin(), frame->memory_data_map.end(), FN(x.second == memblock.data_state));
if (it_data == frame->memory_data_map.end())
fmt::throw_exception("requested memory data state for command not found in memory_data_map");
- const auto& data_block = it_data->second;
+ const auto& data_block = it_data->first;
std::memcpy(vm::base(get_address(memblock.offset, memblock.location)), data_block.data.data(), data_block.data.size());
}
if (replay_cmd.display_buffer_state != 0 && replay_cmd.display_buffer_state != cs.display_buffer_hash)
{
- auto it = frame->display_buffers_map.find(replay_cmd.display_buffer_state);
+ auto it = std::find_if(frame->display_buffers_map.begin(), frame->display_buffers_map.end(), FN(x.second == replay_cmd.display_buffer_state));
if (it == frame->display_buffers_map.end())
fmt::throw_exception("requested display buffer for command not found");
- const auto& dbstate = it->second;
+ const auto& dbstate = it->first;
for (u32 i = 0; i < dbstate.count; ++i)
{
const auto& buf = dbstate.buffers[i];
@@ -136,16 +136,17 @@ namespace rsx
sys_rsx_context_attribute(context_id, 0x104, i,
u64{dbstate.buffers[i].width} << 32 | dbstate.buffers[i].height, u64{dbstate.buffers[i].pitch} << 32 | dbstate.buffers[i].offset, 0);
}
+
cs.display_buffer_hash = replay_cmd.display_buffer_state;
}
if (replay_cmd.tile_state != 0 && replay_cmd.tile_state != cs.tile_hash)
{
- auto it = frame->tile_map.find(replay_cmd.tile_state);
+ auto it = std::find_if(frame->tile_map.begin(), frame->tile_map.end(), FN(x.second == replay_cmd.tile_state));
if (it == frame->tile_map.end())
fmt::throw_exception("requested tile state command not found");
- const auto& tstate = it->second;
+ const auto& tstate = it->first;
for (u32 i = 0; i < limits::tiles_count; ++i)
{
const auto& ti = tstate.tiles[i];
diff --git a/rpcs3/Emu/RSX/Capture/rsx_replay.h b/rpcs3/Emu/RSX/Capture/rsx_replay.h
index 891542f5c5..f11f2e08e9 100644
--- a/rpcs3/Emu/RSX/Capture/rsx_replay.h
+++ b/rpcs3/Emu/RSX/Capture/rsx_replay.h
@@ -11,7 +11,7 @@ namespace rsx
enum : u32
{
c_fc_magic = "RRC"_u32,
- c_fc_version = 0x5,
+ c_fc_version = 0x6,
};
struct frame_capture_data
@@ -92,19 +92,60 @@ namespace rsx
u32 version = c_fc_version;
u32 LE_format = std::endian::little == std::endian::native;
- // hashmap of holding various states for tile
- std::unordered_map tile_map;
- // hashmap of various memory 'changes' that can be applied to ps3 memory
- std::unordered_map memory_map;
- // hashmap of memory blocks that can be applied, this is split from above for size decrease
- std::unordered_map memory_data_map;
- // display buffer state map
- std::unordered_map display_buffers_map;
- // actual command queue to hold everything above
+ struct bitwise_hasher
+ {
+ template
+ usz operator()(const T& key) const noexcept
+ {
+ if constexpr (!!(requires (const T& a) { a.data[0]; }))
+ {
+ return std::hash{}(std::string_view{ reinterpret_cast(key.data.data()), key.data.size() * sizeof(key.data[0]) });
+ }
+
+ return std::hash{}(std::string_view{ reinterpret_cast(&key), sizeof(key) });
+ }
+
+ template
+ bool operator()(const T& keya, const T& keyb) const noexcept
+ {
+ if constexpr (!!(requires (const T& a) { a.data[0]; }))
+ {
+ if (keya.data.size() != keyb.data.size())
+ {
+ return false;
+ }
+
+ return std::equal(keya.data.begin(), keya.data.end(), keyb.data.begin());
+ }
+
+ return std::equal(reinterpret_cast(&keya), reinterpret_cast(&keya) + sizeof(T), reinterpret_cast(&keyb));
+ }
+ };
+
+ template
+ using uno_bit_map = std::unordered_map;
+
+ // Hashmap of holding various states for tile
+ uno_bit_map tile_map;
+
+ // Hashmap of various memory 'changes' that can be applied to ps3 memory
+ uno_bit_map memory_map;
+
+ // Hashmap of memory blocks that can be applied, this is split from above for size decrease
+ uno_bit_map memory_data_map;
+
+ // Display buffer state map
+ uno_bit_map display_buffers_map;
+
+ // Actual command queue to hold everything above
std::vector replay_commands;
+
// Initial registers state at the beginning of the capture
rsx::rsx_state reg_state;
+ // Indexer for memory blocks
+ u64 memory_indexer = 0x1234;
+
void reset()
{
magic = c_fc_magic;
diff --git a/rpcs3/util/serialization.hpp b/rpcs3/util/serialization.hpp
index 120c70c606..5e139e05f8 100644
--- a/rpcs3/util/serialization.hpp
+++ b/rpcs3/util/serialization.hpp
@@ -6,7 +6,7 @@
namespace utils
{
template
- concept FastRandomAccess = requires (T& obj)
+ concept FastRandomAccess = requires (const T& obj)
{
std::data(obj)[std::size(obj)];
};
@@ -24,13 +24,13 @@ namespace utils
};
template
- concept TupleAlike = requires ()
+ concept TupleAlike = (!FastRandomAccess) && requires ()
{
- std::tuple_size>::value;
+ std::tuple_size>::value;
};
template
- concept ListAlike = requires (T& obj) { obj.insert(obj.end(), std::declval()); };
+ concept ListAlike = requires (std::remove_cvref_t& obj) { obj.insert(obj.end(), std::declval()); };
struct serial;
@@ -249,6 +249,15 @@ public:
return raw_serialize(std::addressof(obj), sizeof(obj));
}
+ template
+ static constexpr usz c_tup_size = std::tuple_size_v, std::remove_cvref_t, std::tuple<>>>;
+
+ template
+ static std::remove_cvref_t& as_nonconst(T&& arg) noexcept
+ {
+ return const_cast&>(static_cast(arg));
+ }
+
// std::vector, std::basic_string
// Discourage using std::pair/tuple with vectors because it eliminates the possibility of bitwise optimization
template requires FastRandomAccess && ListAlike && (!TupleAlike)
@@ -327,9 +336,24 @@ public:
{
for (auto&& value : obj)
{
- if (!serialize(value))
+ if constexpr (c_tup_size == 2)
{
- return false;
+ if (!serialize(as_nonconst(std::get<0>(value))))
+ {
+ return false;
+ }
+
+ if (!serialize(as_nonconst(std::get<1>(value))))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!serialize(value))
+ {
+ return false;
+ }
}
}
@@ -347,9 +371,24 @@ public:
for (auto&& value : obj)
{
- if (!serialize(value))
+ if constexpr (c_tup_size == 2)
{
- return false;
+ if (!serialize(as_nonconst(std::get<0>(value))))
+ {
+ return false;
+ }
+
+ if (!serialize(as_nonconst(std::get<1>(value))))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!serialize(value))
+ {
+ return false;
+ }
}
}
@@ -412,7 +451,7 @@ public:
}
// std::pair, std::tuple
- template requires TupleAlike && (!FastRandomAccess)
+ template requires TupleAlike
bool serialize(T& obj)
{
return serialize_tuple(obj);
@@ -423,7 +462,7 @@ public:
bool operator()(Args&&... args) noexcept
{
return ((AUDIT(!std::is_const_v> || is_writing())
- , serialize(const_cast&>(static_cast(args)))), ...);
+ , serialize(as_nonconst(args))), ...);
}
// Code style utility, for when utils::serial is a pointer for example
@@ -519,30 +558,48 @@ public:
AUDIT(!is_writing());
using type = std::remove_const_t;
+ using not_tuple_t = std::conditional_t, char, type>;
if constexpr (Bitcopy)
{
- u8 buf[sizeof(type)]{};
+ u8 buf[sizeof(not_tuple_t)]{};
ensure(raw_serialize(buf, sizeof(buf)));
- return std::bit_cast(buf);
- }
- else if constexpr (std::is_constructible_v>)
- {
- return type(stx::exact_t(*this));
- }
- else if constexpr (std::is_constructible_v)
- {
- type value{};
- ensure(serialize(value));
- return value;
+ return std::bit_cast(buf);
}
else if constexpr (TupleAlike)
{
- static_assert(std::tuple_size_v == 2, "Unimplemented tuple serialization!");
+ constexpr usz tup_size = c_tup_size;
- auto first = operator std::remove_cvref_t(std::declval()))>();
- return type{ std::move(first)
- , operator std::remove_cvref_t(std::declval()))> };
+ static_assert(tup_size == 2 || tup_size == 4, "Unimplemented tuple serialization!");
+
+ using first_t = std::remove_cvref_t(0, tup_size - 1)>(std::declval()))>;
+ using second_t = std::remove_cvref_t(1, tup_size - 1)>(std::declval()))>;
+ using third_t = std::remove_cvref_t(2, tup_size - 1)>(std::declval()))>;
+ using fourth_t = std::remove_cvref_t(3, tup_size - 1)>(std::declval()))>;
+
+ first_t first = this->operator first_t();
+
+ if constexpr (tup_size == 4)
+ {
+ second_t second = this->operator second_t();
+ third_t third = this->operator third_t();
+
+ return type{ std::move(first), std::move(second), std::move(third), this->operator fourth_t() };
+ }
+ else
+ {
+ return type{ std::move(first), this->operator second_t() };
+ }
+ }
+ else if constexpr (std::is_constructible_v>)
+ {
+ return not_tuple_t(stx::exact_t(*this));
+ }
+ else if constexpr (std::is_constructible_v)
+ {
+ not_tuple_t value{};
+ ensure(serialize(value));
+ return value;
}
}