rsx/vk: Implement bulk aligned allocator
- Avoids wasting space and allows use of natural arrays in shaders
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "util/asm.hpp"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
/**
|
||||
* Ring buffer memory helper :
|
||||
* There are 2 "pointers" (offset inside a memory buffer to be provided by class derivative)
|
||||
@@ -166,4 +168,35 @@ public:
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
// Bulk static allocator. Allows to allocate one large block and subdivide
|
||||
// [ 0, 1, 2, 3 ] <pad> [ 4, 5, 6, 7 ] ...
|
||||
template <usz Alignment, usz ElementSize = Alignment>
|
||||
struct bulk_allocator
|
||||
{
|
||||
bulk_allocator(data_heap& container, u32 batch_size = 1)
|
||||
: m_container(container)
|
||||
, m_batch_size(batch_size)
|
||||
{}
|
||||
|
||||
usz alloc()
|
||||
{
|
||||
if (!m_capacity)
|
||||
{
|
||||
m_address = m_container.alloc<Alignment>(ElementSize * m_batch_size);
|
||||
m_capacity = m_batch_size;
|
||||
}
|
||||
|
||||
m_capacity--;
|
||||
return std::exchange(m_address, m_address + ElementSize);
|
||||
}
|
||||
|
||||
private:
|
||||
data_heap& m_container;
|
||||
usz m_address = 0;
|
||||
|
||||
u32 m_capacity = 0;
|
||||
u32 m_batch_size = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace vk
|
||||
|
||||
void data_heap::create(VkBufferUsageFlags usage, usz size, rsx::flags32_t flags, const char* name, usz guard, VkBool32 notify)
|
||||
{
|
||||
::data_heap::init(size, name, guard);
|
||||
rsx::data_heap::init(size, name, guard);
|
||||
|
||||
const auto& memory_map = g_render_device->get_memory_mapping();
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace vk
|
||||
auto memory_index = m_prefer_writethrough ? memory_map.device_bar : memory_map.host_visible_coherent;
|
||||
|
||||
// Update heap information and reset the allocator
|
||||
::data_heap::init(aligned_new_size, m_name, m_min_guard_size);
|
||||
rsx::data_heap::init(aligned_new_size, m_name, m_min_guard_size);
|
||||
|
||||
// Discard old heap and create a new one. Old heap will be garbage collected when no longer needed
|
||||
auto gc = get_resource_manager();
|
||||
@@ -188,7 +188,7 @@ namespace vk
|
||||
return after_usage < limit;
|
||||
}
|
||||
|
||||
void* data_heap::map(usz offset, usz size)
|
||||
void* data_heap::map_impl(usz offset, usz size)
|
||||
{
|
||||
if (!_ptr)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace vk
|
||||
heap_pool_force_vram_shadow = (1 << 2),
|
||||
};
|
||||
|
||||
class data_heap : public ::data_heap
|
||||
class data_heap : public rsx::data_heap
|
||||
{
|
||||
private:
|
||||
usz initial_size = 0;
|
||||
@@ -41,6 +41,8 @@ namespace vk
|
||||
bool grow(usz size) override;
|
||||
bool can_allocate_heap(const vk::memory_type_info& target_heap, usz size, int max_usage_percent);
|
||||
|
||||
void* map_impl(usz offset, usz size);
|
||||
|
||||
public:
|
||||
std::unique_ptr<buffer> heap;
|
||||
|
||||
@@ -51,9 +53,16 @@ namespace vk
|
||||
void create(VkBufferUsageFlags usage, usz size, rsx::flags32_t flags, const char* name, usz guard = 0x10000, VkBool32 notify = VK_FALSE);
|
||||
void destroy();
|
||||
|
||||
void* map(usz offset, usz size);
|
||||
template <typename T = void>
|
||||
T* map(usz offset, usz size)
|
||||
{
|
||||
return reinterpret_cast<T*>(map_impl(offset, size));
|
||||
}
|
||||
|
||||
void unmap(bool force = false);
|
||||
|
||||
void sync(const vk::command_buffer& cmd);
|
||||
|
||||
template<int Alignment, typename T = char>
|
||||
requires std::is_trivially_destructible_v<T>
|
||||
std::pair<usz, T*> alloc_and_map(usz count)
|
||||
@@ -63,8 +72,6 @@ namespace vk
|
||||
return { addr, reinterpret_cast<T*>(map(addr, size_bytes)) };
|
||||
}
|
||||
|
||||
void sync(const vk::command_buffer& cmd);
|
||||
|
||||
template <usz Alignment>
|
||||
VkDescriptorBufferInfoEx window(usz offset, usz range, u64 window_size) const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user