Remove xxHash submodule

This commit is contained in:
Elad 2025-02-14 16:59:16 +02:00
parent 0e5014788b
commit 52edef0867
11 changed files with 187 additions and 169 deletions

4
.gitmodules vendored
View file

@ -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

View file

@ -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)

1
3rdparty/xxHash vendored

@ -1 +0,0 @@
Subproject commit e626a72bc2321cd320e953a0ccf1584cad60f363

View file

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{939FE206-1182-ABC3-1234-FEAB88E98404}</ProjectGuid>
</PropertyGroup>
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="xxHash/xxhash.c" />
</ItemGroup>
<ItemGroup>
<Text Include="LICENSE" />
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="xxHash/xxhash.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -3,7 +3,7 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>.\;..\;..\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</IncludePath>
<IncludePath>.\;..\;..\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</IncludePath>
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
@ -23,7 +23,7 @@
<AdditionalOptions>/utf-8 /Zc:throwingNew- /constexpr:steps16777216 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>xxhash.lib;ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib</AdditionalDependencies>
<AdditionalDependencies>ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\ffmpeg\lib\windows\x86_64</AdditionalLibraryDirectories>
<StackReserveSize>8388608</StackReserveSize>
<StackCommitSize>1048576</StackCommitSize>

View file

@ -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}

View file

@ -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)

View file

@ -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<u64>& 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<u64>& 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<u64>& 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;

View file

@ -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];

View file

@ -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<u64, tile_state> tile_map;
// hashmap of various memory 'changes' that can be applied to ps3 memory
std::unordered_map<u64, memory_block> memory_map;
// hashmap of memory blocks that can be applied, this is split from above for size decrease
std::unordered_map<u64, memory_block_data> memory_data_map;
// display buffer state map
std::unordered_map<u64, display_buffers_state> display_buffers_map;
// actual command queue to hold everything above
struct bitwise_hasher
{
template <typename T>
usz operator()(const T& key) const noexcept
{
if constexpr (!!(requires (const T& a) { a.data[0]; }))
{
return std::hash<std::string_view>{}(std::string_view{ reinterpret_cast<const char*>(key.data.data()), key.data.size() * sizeof(key.data[0]) });
}
return std::hash<std::string_view>{}(std::string_view{ reinterpret_cast<const char*>(&key), sizeof(key) });
}
template <typename T>
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<const char*>(&keya), reinterpret_cast<const char*>(&keya) + sizeof(T), reinterpret_cast<const char*>(&keyb));
}
};
template <typename T, typename V>
using uno_bit_map = std::unordered_map<T, V, bitwise_hasher, bitwise_hasher>;
// Hashmap of holding various states for tile
uno_bit_map<tile_state, u64> tile_map;
// Hashmap of various memory 'changes' that can be applied to ps3 memory
uno_bit_map<memory_block, u64> memory_map;
// Hashmap of memory blocks that can be applied, this is split from above for size decrease
uno_bit_map<memory_block_data, u64> memory_data_map;
// Display buffer state map
uno_bit_map<display_buffers_state, u64> display_buffers_map;
// Actual command queue to hold everything above
std::vector<replay_command> 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;

View file

@ -6,7 +6,7 @@
namespace utils
{
template <typename T>
concept FastRandomAccess = requires (T& obj)
concept FastRandomAccess = requires (const T& obj)
{
std::data(obj)[std::size(obj)];
};
@ -24,13 +24,13 @@ namespace utils
};
template <typename T>
concept TupleAlike = requires ()
concept TupleAlike = (!FastRandomAccess<T>) && requires ()
{
std::tuple_size<std::remove_cv_t<T>>::value;
std::tuple_size<std::remove_cvref_t<T>>::value;
};
template <typename T>
concept ListAlike = requires (T& obj) { obj.insert(obj.end(), std::declval<typename T::value_type>()); };
concept ListAlike = requires (std::remove_cvref_t<T>& obj) { obj.insert(obj.end(), std::declval<typename T::value_type>()); };
struct serial;
@ -249,6 +249,15 @@ public:
return raw_serialize(std::addressof(obj), sizeof(obj));
}
template <typename T>
static constexpr usz c_tup_size = std::tuple_size_v<std::conditional_t<TupleAlike<T>, std::remove_cvref_t<T>, std::tuple<>>>;
template <typename T>
static std::remove_cvref_t<T>& as_nonconst(T&& arg) noexcept
{
return const_cast<std::remove_cvref_t<T>&>(static_cast<const T&>(arg));
}
// std::vector, std::basic_string
// Discourage using std::pair/tuple with vectors because it eliminates the possibility of bitwise optimization
template <typename T> requires FastRandomAccess<T> && ListAlike<T> && (!TupleAlike<typename T::value_type>)
@ -327,9 +336,24 @@ public:
{
for (auto&& value : obj)
{
if (!serialize(value))
if constexpr (c_tup_size<decltype(*std::data(obj))> == 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<decltype(value)> == 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 <typename T> requires TupleAlike<T> && (!FastRandomAccess<T>)
template <typename T> requires TupleAlike<T>
bool serialize(T& obj)
{
return serialize_tuple(obj);
@ -423,7 +462,7 @@ public:
bool operator()(Args&&... args) noexcept
{
return ((AUDIT(!std::is_const_v<std::remove_reference_t<Args>> || is_writing())
, serialize(const_cast<std::remove_cvref_t<Args>&>(static_cast<const Args&>(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<T>;
using not_tuple_t = std::conditional_t<TupleAlike<T>, char, type>;
if constexpr (Bitcopy<T>)
{
u8 buf[sizeof(type)]{};
u8 buf[sizeof(not_tuple_t)]{};
ensure(raw_serialize(buf, sizeof(buf)));
return std::bit_cast<type>(buf);
}
else if constexpr (std::is_constructible_v<type, stx::exact_t<serial&>>)
{
return type(stx::exact_t<serial&>(*this));
}
else if constexpr (std::is_constructible_v<type>)
{
type value{};
ensure(serialize(value));
return value;
return std::bit_cast<not_tuple_t>(buf);
}
else if constexpr (TupleAlike<T>)
{
static_assert(std::tuple_size_v<type> == 2, "Unimplemented tuple serialization!");
constexpr usz tup_size = c_tup_size<type>;
auto first = operator std::remove_cvref_t<decltype(std::get<0>(std::declval<type&>()))>();
return type{ std::move(first)
, operator std::remove_cvref_t<decltype(std::get<1>(std::declval<type&>()))> };
static_assert(tup_size == 2 || tup_size == 4, "Unimplemented tuple serialization!");
using first_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(0, tup_size - 1)>(std::declval<type&>()))>;
using second_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(1, tup_size - 1)>(std::declval<type&>()))>;
using third_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(2, tup_size - 1)>(std::declval<type&>()))>;
using fourth_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(3, tup_size - 1)>(std::declval<type&>()))>;
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<type, stx::exact_t<serial&>>)
{
return not_tuple_t(stx::exact_t<serial&>(*this));
}
else if constexpr (std::is_constructible_v<type>)
{
not_tuple_t value{};
ensure(serialize(value));
return value;
}
}