video_core: Page manager and memory tracker improvenets (#3155)

* I don't know what to put here

* clang-format

* clang-format 2.0

* Deadlock free locking

* Por boost range lock implementation

* clang-format
This commit is contained in:
Lander Gallastegi
2025-06-26 18:38:53 +02:00
committed by GitHub
parent a49b13fe66
commit 9f37ede336
8 changed files with 176 additions and 42 deletions

View File

@@ -16,7 +16,7 @@ namespace VideoCore {
class MemoryTracker {
public:
static constexpr size_t MAX_CPU_PAGE_BITS = 40;
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS);
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - TRACKER_HIGHER_PAGE_BITS);
static constexpr size_t MANAGER_POOL_SIZE = 32;
public:
@@ -90,11 +90,11 @@ private:
using FuncReturn = typename std::invoke_result<Func, RegionManager*, u64, size_t>::type;
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
std::size_t remaining_size{size};
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
u64 page_offset{cpu_address & HIGHER_PAGE_MASK};
std::size_t page_index{cpu_address >> TRACKER_HIGHER_PAGE_BITS};
u64 page_offset{cpu_address & TRACKER_HIGHER_PAGE_MASK};
while (remaining_size > 0) {
const std::size_t copy_amount{
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
std::min<std::size_t>(TRACKER_HIGHER_PAGE_SIZE - page_offset, remaining_size)};
auto* manager{top_tier[page_index]};
if (manager) {
if constexpr (BOOL_BREAK) {
@@ -123,7 +123,7 @@ private:
}
void CreateRegion(std::size_t page_index) {
const VAddr base_cpu_addr = page_index << HIGHER_PAGE_BITS;
const VAddr base_cpu_addr = page_index << TRACKER_HIGHER_PAGE_BITS;
if (free_managers.empty()) {
manager_pool.emplace_back();
auto& last_pool = manager_pool.back();

View File

@@ -9,13 +9,13 @@
namespace VideoCore {
constexpr u64 PAGES_PER_WORD = 64;
constexpr u64 BYTES_PER_PAGE = 4_KB;
constexpr u64 TRACKER_PAGE_BITS = 12; // 4K pages
constexpr u64 TRACKER_BYTES_PER_PAGE = 1ULL << TRACKER_PAGE_BITS;
constexpr u64 HIGHER_PAGE_BITS = 22;
constexpr u64 HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS;
constexpr u64 HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL;
constexpr u64 NUM_REGION_PAGES = HIGHER_PAGE_SIZE / BYTES_PER_PAGE;
constexpr u64 TRACKER_HIGHER_PAGE_BITS = 24; // each region is 16MB
constexpr u64 TRACKER_HIGHER_PAGE_SIZE = 1ULL << TRACKER_HIGHER_PAGE_BITS;
constexpr u64 TRACKER_HIGHER_PAGE_MASK = TRACKER_HIGHER_PAGE_SIZE - 1ULL;
constexpr u64 NUM_PAGES_PER_REGION = TRACKER_HIGHER_PAGE_SIZE / TRACKER_BYTES_PER_PAGE;
enum class Type {
CPU,
@@ -23,6 +23,6 @@ enum class Type {
Writeable,
};
using RegionBits = Common::BitArray<NUM_REGION_PAGES>;
using RegionBits = Common::BitArray<NUM_PAGES_PER_REGION>;
} // namespace VideoCore

View File

@@ -83,9 +83,10 @@ public:
void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) {
RENDERER_TRACE;
const size_t offset = dirty_addr - cpu_addr;
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
const size_t end_page =
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
return;
}
std::scoped_lock lk{lock};
@@ -114,9 +115,10 @@ public:
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, auto&& func) {
RENDERER_TRACE;
const size_t offset = query_cpu_range - cpu_addr;
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
const size_t end_page =
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
return;
}
std::scoped_lock lk{lock};
@@ -131,7 +133,7 @@ public:
}
for (const auto& [start, end] : mask) {
func(cpu_addr + start * BYTES_PER_PAGE, (end - start) * BYTES_PER_PAGE);
func(cpu_addr + start * TRACKER_BYTES_PER_PAGE, (end - start) * TRACKER_BYTES_PER_PAGE);
}
if constexpr (clear) {
@@ -151,9 +153,10 @@ public:
template <Type type>
[[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept {
RENDERER_TRACE;
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
const size_t end_page =
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
return false;
}
// std::scoped_lock lk{lock}; // Is this needed?