diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 16147bb8d1..3217cc38f5 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -188,6 +188,8 @@ if(BUILD_RPCS3_TESTS) PRIVATE tests/test.cpp tests/test_fmt.cpp + tests/test_pair.cpp + tests/test_tuple.cpp tests/test_simple_array.cpp tests/test_address_range.cpp ) diff --git a/rpcs3/Emu/RSX/Common/simple_array.hpp b/rpcs3/Emu/RSX/Common/simple_array.hpp index 6fd18ddd1d..090c51d674 100644 --- a/rpcs3/Emu/RSX/Common/simple_array.hpp +++ b/rpcs3/Emu/RSX/Common/simple_array.hpp @@ -196,7 +196,7 @@ namespace rsx if (is_local_storage()) { // Switch to heap storage - _data = static_cast(std::malloc(sizeof(Ty) * size)); + ensure(_data = static_cast(std::malloc(sizeof(Ty) * size))); std::memcpy(static_cast(_data), _local_storage, size_bytes()); } else diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 3a80793f77..5fa595a80b 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -9,6 +9,7 @@ #include #include "util/asm.hpp" +#include "util/pair.hpp" namespace rsx { @@ -244,10 +245,9 @@ namespace rsx template void intersect_surface_region(command_list_type cmd, u32 address, surface_type new_surface, surface_type prev_surface) { - auto scan_list = [&new_surface, address](const rsx::address_range32& mem_range, - surface_ranged_map& data) -> rsx::simple_array> + auto scan_list = [&new_surface, address](const rsx::address_range32& mem_range, surface_ranged_map& data) { - rsx::simple_array> result; + rsx::simple_array> result; for (auto it = data.begin_range(mem_range); it != data.end(); ++it) { auto surface = Traits::get(it->second); @@ -314,7 +314,7 @@ namespace rsx } } - rsx::simple_array> surface_info; + rsx::simple_array> surface_info; if (list1.empty()) { surface_info = std::move(list2); @@ -1091,7 +1091,7 @@ namespace rsx rsx::simple_array get_merged_texture_memory_region(commandbuffer_type& cmd, u32 texaddr, u32 required_width, u32 required_height, u32 required_pitch, u8 required_bpp, rsx::surface_access access) { rsx::simple_array result; - rsx::simple_array> dirty; + rsx::simple_array> dirty; const auto surface_internal_pitch = (required_width * required_bpp); diff --git a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp index 7383c0d7fa..9606ca7b16 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/GL/GLShaderInterpreter.cpp @@ -387,7 +387,7 @@ namespace gl allocator.pools[i].flags = 0; } - rsx::simple_array> replacement_map; + rsx::simple_array> replacement_map; for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) { if (reference_mask & (1 << i)) diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index c5f6673723..0bbea41832 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -736,6 +736,8 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9c09dd791a..65cd509f85 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -2758,6 +2758,12 @@ Utilities + + Utilities + + + Utilities + diff --git a/rpcs3/tests/rpcs3_test.vcxproj b/rpcs3/tests/rpcs3_test.vcxproj index c458653fda..4f0d136a9a 100644 --- a/rpcs3/tests/rpcs3_test.vcxproj +++ b/rpcs3/tests/rpcs3_test.vcxproj @@ -90,6 +90,8 @@ + + @@ -102,4 +104,4 @@ - + \ No newline at end of file diff --git a/rpcs3/tests/test_pair.cpp b/rpcs3/tests/test_pair.cpp new file mode 100644 index 0000000000..086f7102b6 --- /dev/null +++ b/rpcs3/tests/test_pair.cpp @@ -0,0 +1,46 @@ +#include + +#include "util/types.hpp" +#include "util/pair.hpp" + +struct some_struct +{ + u64 v {}; + char s[12] = "Hello World"; + + bool operator == (const some_struct& r) const + { + return v == r.v && std::memcmp(s, r.s, sizeof(s)) == 0; + } +}; + +TEST(Utils, Pair) +{ + some_struct s {}; + s.v = 1234; + + utils::pair p; + EXPECT_EQ(sizeof(p), 32); + EXPECT_EQ(p.first, 0); + EXPECT_EQ(p.second, some_struct{}); + + p = { 666, s }; + EXPECT_EQ(p.first, 666); + EXPECT_EQ(p.second, s); + + const utils::pair p1 = p; + EXPECT_EQ(p.first, 666); + EXPECT_EQ(p.second, s); + EXPECT_EQ(p1.first, 666); + EXPECT_EQ(p1.second, s); + + utils::pair p2 = p1; + EXPECT_EQ(p1.first, 666); + EXPECT_EQ(p1.second, s); + EXPECT_EQ(p2.first, 666); + EXPECT_EQ(p2.second, s); + + utils::pair p3 = std::move(p); + EXPECT_EQ(p3.first, 666); + EXPECT_EQ(p3.second, s); +} diff --git a/rpcs3/tests/test_simple_array.cpp b/rpcs3/tests/test_simple_array.cpp index 6fc9107e48..c581ab2277 100644 --- a/rpcs3/tests/test_simple_array.cpp +++ b/rpcs3/tests/test_simple_array.cpp @@ -1,5 +1,7 @@ #include +#include "util/pair.hpp" + #define private public #include "Emu/RSX/Common/simple_array.hpp" #undef private @@ -240,4 +242,29 @@ namespace rsx EXPECT_EQ(sum, 15); } + + TEST(SimpleArray, SimplePair) + { + struct some_struct + { + u64 v {}; + char s[12] = "Hello World"; + }; + some_struct s {}; + + rsx::simple_array> arr; + for (int i = 0; i < 5; ++i) + { + s.v = i; + arr.push_back(utils::pair(i, s)); + } + + EXPECT_EQ(arr.size(), 5); + for (int i = 0; i < 5; ++i) + { + EXPECT_EQ(arr[i].first, i); + EXPECT_EQ(arr[i].second.v, i); + EXPECT_EQ(std::memcmp(arr[i].second.s, "Hello World", sizeof(arr[i].second.s)), 0); + } + } } diff --git a/rpcs3/tests/test_tuple.cpp b/rpcs3/tests/test_tuple.cpp new file mode 100644 index 0000000000..2a174d85d3 --- /dev/null +++ b/rpcs3/tests/test_tuple.cpp @@ -0,0 +1,114 @@ +#include + +#include "util/tuple.hpp" + +struct some_struct +{ + u64 v {}; + char s[12] = "Hello World"; + + bool operator == (const some_struct& r) const + { + return v == r.v && std::memcmp(s, r.s, sizeof(s)) == 0; + } +}; + +TEST(Utils, Tuple) +{ + some_struct s {}; + s.v = 1234; + + utils::tuple t0 = {}; + EXPECT_EQ(t0.size(), 0); + + utils::tuple t; + EXPECT_EQ(sizeof(t), sizeof(int)); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_EQ(t.size(), 1); + EXPECT_EQ(t.get<0>(), 0); + + utils::tuple t1 = 2; + EXPECT_EQ(sizeof(t1), sizeof(int)); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_EQ(t1.size(), 1); + EXPECT_EQ(t1.get<0>(), 2); + t1 = {}; + EXPECT_EQ(t1.size(), 1); + EXPECT_EQ(t1.get<0>(), 0); + + utils::tuple t2 = { 2, s }; + EXPECT_EQ(sizeof(t2), 32); + EXPECT_EQ(t2.size(), 2); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_EQ(t2.get<0>(), 2); + EXPECT_EQ(t2.get<1>(), s); + t2 = {}; + EXPECT_EQ(t2.size(), 2); + EXPECT_EQ(t2.get<0>(), 0); + EXPECT_EQ(t2.get<1>(), some_struct{}); + + t2.get<0>() = 666; + t2.get<1>() = s; + EXPECT_EQ(t2.get<0>(), 666); + EXPECT_EQ(t2.get<1>(), s); + + utils::tuple t3 = { 2, s, 1234.0 }; + EXPECT_EQ(sizeof(t3), 40); + EXPECT_EQ(t3.size(), 3); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_TRUE((std::is_same_v()), double&>)); + EXPECT_EQ(t3.get<0>(), 2); + EXPECT_EQ(t3.get<1>(), s); + EXPECT_EQ(t3.get<2>(), 1234.0); + t3 = {}; + EXPECT_EQ(t3.size(), 3); + EXPECT_EQ(t3.get<0>(), 0); + EXPECT_EQ(t3.get<1>(), some_struct{}); + EXPECT_EQ(t3.get<2>(), 0.0); + + t3.get<0>() = 666; + t3.get<1>() = s; + t3.get<2>() = 7.0; + EXPECT_EQ(t3.get<0>(), 666); + EXPECT_EQ(t3.get<1>(), s); + EXPECT_EQ(t3.get<2>(), 7.0); + + // const + const utils::tuple tc = { 2, s }; + EXPECT_EQ(tc.size(), 2); + EXPECT_TRUE((std::is_same_v()), const int&>)); + EXPECT_TRUE((std::is_same_v()), const some_struct&>)); + EXPECT_EQ(tc.get<0>(), 2); + EXPECT_EQ(tc.get<1>(), s); + + // assignment + const utils::tuple ta1 = { 2, s }; + utils::tuple ta = ta1; + EXPECT_EQ(ta.size(), 2); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_EQ(ta.get<0>(), 2); + EXPECT_EQ(ta.get<1>(), s); + + utils::tuple ta2 = { 2, s }; + ta = ta2; + EXPECT_EQ(ta.size(), 2); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_EQ(ta.get<0>(), 2); + EXPECT_EQ(ta.get<1>(), s); + EXPECT_EQ(ta2.size(), 2); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_EQ(ta2.get<0>(), 2); + EXPECT_EQ(ta2.get<1>(), s); + + ta = std::move(ta2); + EXPECT_EQ(ta.size(), 2); + EXPECT_TRUE((std::is_same_v()), int&>)); + EXPECT_TRUE((std::is_same_v()), some_struct&>)); + EXPECT_EQ(ta.get<0>(), 2); + EXPECT_EQ(ta.get<1>(), s); +} diff --git a/rpcs3/util/pair.hpp b/rpcs3/util/pair.hpp new file mode 100644 index 0000000000..454054f3ff --- /dev/null +++ b/rpcs3/util/pair.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace utils +{ + template + requires std::is_trivially_copyable_v && std::is_trivially_destructible_v && + std::is_trivially_copyable_v && std::is_trivially_destructible_v + struct pair + { + T1 first {}; + T2 second {}; + }; +} diff --git a/rpcs3/util/tuple.hpp b/rpcs3/util/tuple.hpp new file mode 100644 index 0000000000..7488f7cba4 --- /dev/null +++ b/rpcs3/util/tuple.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "types.hpp" +#include +#include + +namespace utils +{ + template + requires ((std::is_trivially_copyable_v && std::is_trivially_destructible_v) && ...) + struct tuple; + + template <> + struct tuple<> + { + constexpr tuple() = default; + + static constexpr usz size() noexcept { return 0; } + }; + + template + struct tuple : tuple + { + private: + Head head; + + public: + constexpr tuple() + : tuple() + , head{} + {} + + constexpr tuple(Head h, Tail... t) + : tuple(std::forward(t)...) + , head(std::move(h)) + {} + + static constexpr usz size() noexcept + { + return 1 + sizeof...(Tail); + } + + template + requires (N < size()) + constexpr auto& get() + { + if constexpr (N == 0) + return head; + else + return tuple::template get(); + } + + template + requires (N < size()) + constexpr const auto& get() const + { + if constexpr (N == 0) + return head; + else + return tuple::template get(); + } + }; +}