mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
rsx: Rework ranged map
- Adds metadata lookup for intersecting range calculations - Make fetch/put methods more explicit
This commit is contained in:
parent
56540a55ec
commit
43c7417906
@ -10,18 +10,35 @@ namespace rsx
|
||||
template<typename T, int BlockSize>
|
||||
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:
|
||||
using inner_type = typename std::unordered_map<u32, T>;
|
||||
using outer_type = typename std::array<inner_type, 0x100000000ull / BlockSize>;
|
||||
using metadata_array = typename std::array<block_metadata_t, 0x100000000ull / BlockSize>;
|
||||
|
||||
protected:
|
||||
outer_type m_data;
|
||||
metadata_array m_metadata;
|
||||
|
||||
static inline u32 block_for(u32 address)
|
||||
{
|
||||
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:
|
||||
class iterator
|
||||
{
|
||||
@ -33,7 +50,8 @@ namespace rsx
|
||||
inner_type* m_current = 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{};
|
||||
|
||||
inline void forward_scan()
|
||||
@ -67,22 +85,19 @@ namespace rsx
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_current = &(*m_data_ptr)[range.start / BlockSize];
|
||||
m_end = &(*m_data_ptr)[(range.end + 1) / BlockSize];
|
||||
const auto start_block_id = range.start / 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;
|
||||
forward_scan();
|
||||
@ -99,8 +114,9 @@ namespace rsx
|
||||
forward_scan();
|
||||
}
|
||||
|
||||
iterator(super* parent)
|
||||
: m_data_ptr(&parent->m_data)
|
||||
iterator(super* parent):
|
||||
m_data_ptr(parent->m_data.data()),
|
||||
m_metadata_ptr(parent->m_metadata.data())
|
||||
{}
|
||||
|
||||
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)];
|
||||
iterator ret = { this };
|
||||
@ -173,6 +196,18 @@ namespace rsx
|
||||
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)
|
||||
{
|
||||
where.erase();
|
||||
|
@ -153,7 +153,7 @@ namespace rsx
|
||||
|
||||
ensure(region.target == Traits::get(sink));
|
||||
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
|
||||
@ -370,7 +370,7 @@ namespace rsx
|
||||
{
|
||||
// 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 &object = storage[e.first];
|
||||
auto &object = storage.at(e.first);
|
||||
|
||||
ensure(object);
|
||||
|
||||
@ -556,7 +556,7 @@ namespace rsx
|
||||
if (store)
|
||||
{
|
||||
// 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);
|
||||
|
Loading…
Reference in New Issue
Block a user