From 1bb3e3c1cc0cb2dcfb310946eedba47bc9017c9b Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Sun, 19 Jan 2025 18:58:29 -0800 Subject: [PATCH] Some perf-analyzis-driven improvements. - Added a safety variant for hot path operations in the bump allocator and the ordering table. - Unrolled the insert operation for the ordering table. --- .../{bump-allocator.h => bump-allocator.hh} | 11 ++++-- src/mips/psyqo/ordering-table.hh | 16 ++++++--- src/mips/psyqo/shared.hh | 36 +++++++++++++++++++ src/mips/psyqo/src/ordering-table.cpp | 9 ----- 4 files changed, 56 insertions(+), 16 deletions(-) rename src/mips/psyqo/{bump-allocator.h => bump-allocator.hh} (89%) create mode 100644 src/mips/psyqo/shared.hh diff --git a/src/mips/psyqo/bump-allocator.h b/src/mips/psyqo/bump-allocator.hh similarity index 89% rename from src/mips/psyqo/bump-allocator.h rename to src/mips/psyqo/bump-allocator.hh index 25c4e29a7..406a6d21f 100644 --- a/src/mips/psyqo/bump-allocator.h +++ b/src/mips/psyqo/bump-allocator.hh @@ -32,6 +32,7 @@ SOFTWARE. #include "psyqo/fragments.hh" #include "psyqo/kernel.hh" #include "psyqo/primitive-concept.hh" +#include "psyqo/shared.hh" namespace psyqo { @@ -51,13 +52,15 @@ namespace psyqo { * * @tparam N The size of the memory buffer in bytes. */ -template +template class BumpAllocator { public: template Fragments::SimpleFragment

&allocateFragment(Args &&...args) { static constexpr size_t size = sizeof(Fragments::SimpleFragment

); - psyqo::Kernel::assert(remaining() >= size, "BumpAllocator: Out of memory"); + if constexpr (safety == Safe::Yes) { + psyqo::Kernel::assert(remaining() >= size, "BumpAllocator: Out of memory"); + } uint8_t *ptr = m_current; m_current += size; return *new (ptr) Fragments::SimpleFragment

(eastl::forward(args)...); @@ -72,7 +75,9 @@ class BumpAllocator { size += alignedptr - ptr; ptr = alignedptr; } - psyqo::Kernel::assert(remaining() >= size, "BumpAllocator: Out of memory"); + if constexpr (safety == Safe::Yes) { + psyqo::Kernel::assert(remaining() >= size, "BumpAllocator: Out of memory"); + } m_current += size; return *new (ptr) T(eastl::forward(args)...); } diff --git a/src/mips/psyqo/ordering-table.hh b/src/mips/psyqo/ordering-table.hh index 07d2aec9f..b64415f6d 100644 --- a/src/mips/psyqo/ordering-table.hh +++ b/src/mips/psyqo/ordering-table.hh @@ -26,9 +26,11 @@ SOFTWARE. #pragma once +#include #include #include "psyqo/fragment-concept.hh" +#include "psyqo/shared.hh" namespace psyqo { @@ -37,7 +39,6 @@ class GPU; class OrderingTableBase { protected: static void clear(uint32_t* table, size_t size); - static void insert(uint32_t* table, int32_t size, uint32_t* head, uint32_t shiftedFragmentSize, int32_t z); }; /** @@ -54,7 +55,7 @@ class OrderingTableBase { * @tparam N The number of buckets in the ordering table. The larger the number, * the more precise the sorting will be, but the more memory will be used. */ -template +template class OrderingTable : private OrderingTableBase { public: OrderingTable() { clear(); } @@ -74,7 +75,8 @@ class OrderingTable : private OrderingTableBase { * * @details This function inserts a fragment into the ordering table. The fragment * will be inserted into the bucket corresponding to its Z value. Any value outside - * of the range [0, N - 1] will be clamped to the nearest valid value. + * of the range [0, N - 1] will be clamped to the nearest valid value when `safety` + * is set to `Safe::Yes`, which is the default. * * @param frag The fragment to insert. * @param z The Z value of the fragment. @@ -82,7 +84,13 @@ class OrderingTable : private OrderingTableBase { template void insert(Frag& frag, int32_t z) { // TODO: cater for big packets - OrderingTableBase::insert(m_table, N, &frag.head, uint32_t(frag.getActualFragmentSize() << 24), z); + uint32_t* table = m_table + 1; + uint32_t* head = &frag.head; + if constexpr (safety == Safe::Yes) { + z = eastl::clamp(z, int32_t(0), int32_t(N - 1)); + } + *head = (frag.getActualFragmentSize() << 24) | table[z]; + table[z] = reinterpret_cast(head) & 0xffffff; } private: diff --git a/src/mips/psyqo/shared.hh b/src/mips/psyqo/shared.hh new file mode 100644 index 000000000..a748d3447 --- /dev/null +++ b/src/mips/psyqo/shared.hh @@ -0,0 +1,36 @@ +/* + +MIT License + +Copyright (c) 2025 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#pragma once + +namespace psyqo { + +/** + * @brief Shared type for safe and unsafe operations throughout the codebase. + */ +enum class Safe : unsigned { No, Yes }; + +} diff --git a/src/mips/psyqo/src/ordering-table.cpp b/src/mips/psyqo/src/ordering-table.cpp index dfb0d9632..107e15449 100644 --- a/src/mips/psyqo/src/ordering-table.cpp +++ b/src/mips/psyqo/src/ordering-table.cpp @@ -26,18 +26,9 @@ SOFTWARE. #include "psyqo/ordering-table.hh" -#include - void psyqo::OrderingTableBase::clear(uint32_t* table, size_t size) { table[0] = 0xffffff; for (size_t i = 1; i <= size; i++) { table[i] = reinterpret_cast(&table[i - 1]) & 0xffffff; } } - -void psyqo::OrderingTableBase::insert(uint32_t* table, int32_t size, uint32_t* head, uint32_t shiftedFragmentSize, - int32_t z) { - z = eastl::clamp(z, int32_t(0), size) + 1; - *head = shiftedFragmentSize | table[z]; - table[z] = reinterpret_cast(head) & 0xffffff; -}