rsx: Rework ranged map

- Adds metadata lookup for intersecting range calculations
- Make fetch/put methods more explicit
This commit is contained in:
kd-11 2022-03-22 00:04:39 +03:00 committed by kd-11
parent 56540a55ec
commit 43c7417906
2 changed files with 54 additions and 19 deletions

View File

@ -10,18 +10,35 @@ namespace rsx
template<typename T, int BlockSize> template<typename T, int BlockSize>
class ranged_map class ranged_map
{ {
struct block_metadata_t
{
u32 id = umax; // ID of the matadata blob
u32 head_block = umax; // Earliest block that may have an object that intersects with the data at the block with ID 'id'
};
public: public:
using inner_type = typename std::unordered_map<u32, T>; using inner_type = typename std::unordered_map<u32, T>;
using outer_type = typename std::array<inner_type, 0x100000000ull / BlockSize>; using outer_type = typename std::array<inner_type, 0x100000000ull / BlockSize>;
using metadata_array = typename std::array<block_metadata_t, 0x100000000ull / BlockSize>;
protected: protected:
outer_type m_data; outer_type m_data;
metadata_array m_metadata;
static inline u32 block_for(u32 address) static inline u32 block_for(u32 address)
{ {
return address / BlockSize; return address / BlockSize;
} }
void broadcast_insert(const utils::address_range& range)
{
const auto head_block = block_for(range.start);
for (auto meta = &m_metadata[head_block]; meta <= &m_metadata[block_for(range.end)]; ++meta)
{
meta->head_block = std::min(head_block, meta->head_block);
}
}
public: public:
class iterator class iterator
{ {
@ -33,7 +50,8 @@ namespace rsx
inner_type* m_current = nullptr; inner_type* m_current = nullptr;
inner_type* m_end = nullptr; inner_type* m_end = nullptr;
outer_type* m_data_ptr = nullptr; inner_type* m_data_ptr = nullptr;
block_metadata_t* m_metadata_ptr = nullptr;
inner_iterator m_it{}; inner_iterator m_it{};
inline void forward_scan() inline void forward_scan()
@ -67,22 +85,19 @@ namespace rsx
forward_scan(); forward_scan();
} }
inline void begin_range(const utils::address_range& range, inner_iterator& where)
{
m_it = where;
m_current = &(*m_data_ptr)[range.start / BlockSize];
m_end = &(*m_data_ptr)[(range.end + 1) / BlockSize];
}
inline void begin_range(u32 address, inner_iterator& where) inline void begin_range(u32 address, inner_iterator& where)
{ {
begin_range(utils::address_range::start_length(address, 1), where); m_current = &m_data_ptr[address / BlockSize];
m_end = m_current;
m_it = where;
} }
inline void begin_range(const utils::address_range& range) inline void begin_range(const utils::address_range& range)
{ {
m_current = &(*m_data_ptr)[range.start / BlockSize]; const auto start_block_id = range.start / BlockSize;
m_end = &(*m_data_ptr)[(range.end + 1) / BlockSize]; const auto& metadata = m_metadata_ptr[start_block_id];
m_current = &m_data_ptr[std::min(start_block_id, metadata.head_block)];
m_end = &m_data_ptr[range.end / BlockSize];
--m_current; --m_current;
forward_scan(); forward_scan();
@ -99,8 +114,9 @@ namespace rsx
forward_scan(); forward_scan();
} }
iterator(super* parent) iterator(super* parent):
: m_data_ptr(&parent->m_data) m_data_ptr(parent->m_data.data()),
m_metadata_ptr(parent->m_metadata.data())
{} {}
public: public:
@ -154,12 +170,19 @@ namespace rsx
} }
}; };
inline T& operator[](const u32& key) public:
ranged_map()
{ {
return m_data[block_for(key)][key]; std::for_each(m_metadata.begin(), m_metadata.end(), [&](auto& meta) { meta.id = static_cast<u32>(&meta - m_metadata.data()); });
} }
inline auto find(const u32& key) inline void emplace(const utils::address_range& range, T&& value)
{
broadcast_insert(range);
m_data[block_for(range.start)].insert_or_assign(range.start, std::forward<T>(value));
}
inline iterator find(const u32 key)
{ {
auto& block = m_data[block_for(key)]; auto& block = m_data[block_for(key)];
iterator ret = { this }; iterator ret = { this };
@ -173,6 +196,18 @@ namespace rsx
return ret; return ret;
} }
inline T& at(const u32 key)
{
auto& block = m_data[block_for(key)];
if (auto found = block.find(key);
found != block.end())
{
return (*found).second;
}
fmt::throw_exception("Object not found");
}
inline iterator erase(iterator& where) inline iterator erase(iterator& where)
{ {
where.erase(); where.erase();

View File

@ -153,7 +153,7 @@ namespace rsx
ensure(region.target == Traits::get(sink)); ensure(region.target == Traits::get(sink));
orphaned_surfaces.push_back(region.target); orphaned_surfaces.push_back(region.target);
data[new_address] = std::move(sink); data.emplace(region.target->get_memory_range(), std::move(sink));
}; };
// Define incoming region // Define incoming region
@ -370,7 +370,7 @@ namespace rsx
{ {
// This has been 'swallowed' by the new surface and can be safely freed // This has been 'swallowed' by the new surface and can be safely freed
auto &storage = surface->is_depth_surface() ? m_depth_stencil_storage : m_render_targets_storage; auto &storage = surface->is_depth_surface() ? m_depth_stencil_storage : m_render_targets_storage;
auto &object = storage[e.first]; auto &object = storage.at(e.first);
ensure(object); ensure(object);
@ -556,7 +556,7 @@ namespace rsx
if (store) if (store)
{ {
// New surface was found among invalidated surfaces or created from scratch // New surface was found among invalidated surfaces or created from scratch
(*primary_storage)[address] = std::move(new_surface_storage); primary_storage->emplace(new_surface->get_memory_range(), std::move(new_surface_storage));
} }
ensure(!old_surface_storage); ensure(!old_surface_storage);