mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-03 19:28:31 +00:00
Build and Release KytyPS5 / Build KytyPS5 (Windows) (push) Canceled after 0s
Build and Release KytyPS5 / Build KytyPS5 (macOS) (push) Canceled after 0s
Build and Release KytyPS5 / Build KytyPS5 (Linux) (push) Canceled after 0s
Build and Release KytyPS5 / Release KytyPS5 (push) Canceled after 0s
* Per page -> per range search (optimization)
104 lines
2.7 KiB
C++
104 lines
2.7 KiB
C++
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RANGESET_H_
|
|
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RANGESET_H_
|
|
|
|
#include "common/assert.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
namespace Libs::Graphics {
|
|
|
|
class RangeSet final {
|
|
public:
|
|
struct Range {
|
|
uint64_t address = 0;
|
|
uint64_t size = 0;
|
|
};
|
|
|
|
void Add(uint64_t address, uint64_t size) {
|
|
const auto end = End(address, size);
|
|
auto it = m_ranges.lower_bound(address);
|
|
if (it != m_ranges.begin() && std::prev(it)->second >= address) {
|
|
it = std::prev(it);
|
|
}
|
|
uint64_t begin = address;
|
|
uint64_t last = end;
|
|
while (it != m_ranges.end() && it->first <= last) {
|
|
begin = std::min(begin, it->first);
|
|
last = std::max(last, it->second);
|
|
it = m_ranges.erase(it);
|
|
}
|
|
m_ranges.emplace(begin, last);
|
|
}
|
|
|
|
void Subtract(uint64_t address, uint64_t size) {
|
|
const auto end = End(address, size);
|
|
auto it = m_ranges.lower_bound(address);
|
|
if (it != m_ranges.begin() && std::prev(it)->second > address) {
|
|
it = std::prev(it);
|
|
}
|
|
while (it != m_ranges.end() && it->first < end) {
|
|
const auto begin = it->first;
|
|
const auto last = it->second;
|
|
it = m_ranges.erase(it);
|
|
if (begin < address) {
|
|
m_ranges.emplace(begin, address);
|
|
}
|
|
if (last > end) {
|
|
m_ranges.emplace(end, last);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] std::vector<Range> Intersections(uint64_t address, uint64_t size) const {
|
|
std::vector<Range> result;
|
|
ForEachIntersection(address, size, [&result](Range range) { result.push_back(range); });
|
|
return result;
|
|
}
|
|
|
|
[[nodiscard]] bool Contains(uint64_t address, uint64_t size) const {
|
|
const auto end = End(address, size);
|
|
auto it = m_ranges.upper_bound(address);
|
|
if (it == m_ranges.begin()) {
|
|
return false;
|
|
}
|
|
--it;
|
|
return it->first <= address && it->second >= end;
|
|
}
|
|
|
|
template <typename Func>
|
|
void ForEachIntersection(uint64_t address, uint64_t size, Func&& func) const {
|
|
const auto end = End(address, size);
|
|
auto it = m_ranges.upper_bound(address);
|
|
if (it != m_ranges.begin()) {
|
|
--it;
|
|
}
|
|
for (; it != m_ranges.end() && it->first < end; ++it) {
|
|
const auto begin = std::max(address, it->first);
|
|
const auto last = std::min(end, it->second);
|
|
if (begin < last) {
|
|
func(Range {begin, last - begin});
|
|
}
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool Empty() const { return m_ranges.empty(); }
|
|
|
|
private:
|
|
static uint64_t End(uint64_t address, uint64_t size) {
|
|
if (address == 0 || size == 0 || size > UINT64_MAX - address) {
|
|
EXIT("invalid range-set address or size\n");
|
|
}
|
|
return address + size;
|
|
}
|
|
|
|
std::map<uint64_t, uint64_t> m_ranges;
|
|
};
|
|
|
|
} // namespace Libs::Graphics
|
|
|
|
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RANGESET_H_
|