mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 18:39:57 +00:00
vk: Introduce the concept of VRAM allocation pools
- Each buffer or image has to declare which pool it belongs to. This will aid with memory management down the line.
This commit is contained in:
parent
71a5e5333a
commit
88abf3a6ba
@ -67,7 +67,8 @@ namespace vk
|
||||
|
||||
allocated_memory = std::make_unique<vk::buffer>(dev, size,
|
||||
dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0);
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0,
|
||||
VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
s_allocated_dma_pool_size += allocated_memory->size();
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ VKGSRender::VKGSRender() : GSRender()
|
||||
}
|
||||
|
||||
const auto& memory_map = m_device->get_memory_mapping();
|
||||
null_buffer = std::make_unique<vk::buffer>(*m_device, 32, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0);
|
||||
null_buffer = std::make_unique<vk::buffer>(*m_device, 32, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
null_buffer_view = std::make_unique<vk::buffer_view>(*m_device, null_buffer->value, VK_FORMAT_R8_UINT, 0, 32);
|
||||
|
||||
vk::initialize_compiler_context();
|
||||
@ -2461,7 +2461,7 @@ void VKGSRender::begin_conditional_rendering(const std::vector<rsx::reports::occ
|
||||
m_cond_render_buffer = std::make_unique<vk::buffer>(
|
||||
*m_device, 4,
|
||||
memory_props.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
usage_flags, 0);
|
||||
usage_flags, 0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
}
|
||||
|
||||
VkPipelineStageFlags dst_stage;
|
||||
|
@ -365,6 +365,8 @@ private:
|
||||
deadlock = 2
|
||||
};
|
||||
|
||||
using enum vk::vmm_allocation_pool;
|
||||
|
||||
private:
|
||||
VKFragmentProgram m_fragment_prog;
|
||||
VKVertexProgram m_vertex_prog;
|
||||
|
@ -514,7 +514,7 @@ namespace vk
|
||||
auto tex = std::make_unique<vk::image>(dev, dev.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D, format, std::max(w, 1u), std::max(h, 1u), 1, 1, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
0);
|
||||
0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
if (pixel_src && data_size)
|
||||
std::memcpy(addr, pixel_src, data_size);
|
||||
|
@ -655,8 +655,8 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
|
||||
const usz sshot_size = buffer_height * buffer_width * 4;
|
||||
|
||||
vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0);
|
||||
vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
VkBufferImageCopy copy_info;
|
||||
copy_info.bufferOffset = 0;
|
||||
|
@ -26,6 +26,7 @@ namespace vk
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage,
|
||||
0,
|
||||
VMM_ALLOCATION_POOL_SURFACE_CACHE,
|
||||
format_class()));
|
||||
|
||||
resolve_surface->native_component_map = native_component_map;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "vkutils/data_heap.h"
|
||||
#include "vkutils/device.h"
|
||||
#include "vkutils/image.h"
|
||||
#include "vkutils/memory.h"
|
||||
#include "vkutils/scratch.h"
|
||||
|
||||
#include <span>
|
||||
@ -120,7 +121,7 @@ namespace rsx
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0, RSX_FORMAT_CLASS_COLOR);
|
||||
0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, RSX_FORMAT_CLASS_COLOR);
|
||||
|
||||
rtt->set_debug_name(fmt::format("RTV @0x%x", address));
|
||||
rtt->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
@ -181,7 +182,7 @@ namespace rsx
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0, rsx::classify_format(format));
|
||||
0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, rsx::classify_format(format));
|
||||
|
||||
ds->set_debug_name(fmt::format("DSV @0x%x", address));
|
||||
ds->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
@ -223,6 +224,7 @@ namespace rsx
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
ref->info.usage,
|
||||
ref->info.flags,
|
||||
vk::VMM_ALLOCATION_POOL_SURFACE_CACHE,
|
||||
ref->format_class());
|
||||
|
||||
sink->add_ref();
|
||||
|
@ -54,7 +54,7 @@ namespace vk
|
||||
return size / (1024.f * 1024.f * 1024.f);
|
||||
}
|
||||
|
||||
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size)
|
||||
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool)
|
||||
{
|
||||
auto key = reinterpret_cast<uptr>(handle);
|
||||
const vmm_allocation_t info = { memory_size, memory_type };
|
||||
|
@ -264,8 +264,8 @@ namespace vk
|
||||
|
||||
//At worst case, 1 char = 16*16*8 bytes (average about 24*8), so ~256K for 128 chars. Allocating 512k for verts
|
||||
//uniform params are 8k in size, allocating for 120 lines (max lines at 4k, one column per row. Can be expanded
|
||||
m_vertex_buffer = std::make_unique<vk::buffer>(dev, 524288, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0);
|
||||
m_uniforms_buffer = std::make_unique<vk::buffer>(dev, 983040, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0);
|
||||
m_vertex_buffer = std::make_unique<vk::buffer>(dev, 524288, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
m_uniforms_buffer = std::make_unique<vk::buffer>(dev, 983040, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
m_render_pass = render_pass;
|
||||
m_uniform_buffer_size = 983040;
|
||||
|
@ -576,7 +576,7 @@ namespace vk
|
||||
dst_format,
|
||||
w, h, d, mips, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags,
|
||||
rsx::classify_format(gcm_format));
|
||||
VMM_ALLOCATION_POOL_TEXTURE_CACHE, rsx::classify_format(gcm_format));
|
||||
}
|
||||
|
||||
//This method is almost exclusively used to work on framebuffer resources
|
||||
@ -871,7 +871,7 @@ namespace vk
|
||||
vk_format,
|
||||
width, height, depth, mipmaps, layer, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, usage_flags, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0,
|
||||
rsx::classify_format(gcm_format));
|
||||
VMM_ALLOCATION_POOL_TEXTURE_CACHE, rsx::classify_format(gcm_format));
|
||||
|
||||
// New section, we must prepare it
|
||||
region.reset(rsx_range);
|
||||
@ -1220,7 +1220,8 @@ namespace vk
|
||||
VK_IMAGE_TYPE_2D,
|
||||
format,
|
||||
width, height, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED,
|
||||
VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0);
|
||||
VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
0, VMM_ALLOCATION_POOL_TEXTURE_CACHE);
|
||||
|
||||
VkImageSubresource subresource{};
|
||||
subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
@ -39,7 +39,7 @@ namespace vk
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer::buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags)
|
||||
buffer::buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool)
|
||||
: m_device(dev)
|
||||
{
|
||||
info.size = size;
|
||||
@ -62,7 +62,7 @@ namespace vk
|
||||
fmt::throw_exception("No compatible memory type was found!");
|
||||
}
|
||||
|
||||
memory = std::make_unique<memory_block>(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index);
|
||||
memory = std::make_unique<memory_block>(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index, allocation_pool);
|
||||
vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset());
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace vk
|
||||
VkBufferCreateInfo info = {};
|
||||
std::unique_ptr<vk::memory_block> memory;
|
||||
|
||||
buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags);
|
||||
buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool);
|
||||
buffer(const vk::render_device& dev, VkBufferUsageFlags usage, void* host_pointer, u64 size);
|
||||
~buffer();
|
||||
|
||||
|
@ -26,13 +26,13 @@ namespace vk
|
||||
{
|
||||
rsx_log.warning("Buffer usage %u is not heap-compatible using this driver, explicit staging buffer in use", usage);
|
||||
|
||||
shadow = std::make_unique<buffer>(*g_render_device, size, memory_index, memory_flags, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0);
|
||||
shadow = std::make_unique<buffer>(*g_render_device, size, memory_index, memory_flags, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, VMM_ALLOCATION_POOL_SYSTEM);
|
||||
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
memory_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
memory_index = memory_map.device_local;
|
||||
}
|
||||
|
||||
heap = std::make_unique<buffer>(*g_render_device, size, memory_index, memory_flags, usage, 0);
|
||||
heap = std::make_unique<buffer>(*g_render_device, size, memory_index, memory_flags, usage, 0, VMM_ALLOCATION_POOL_SYSTEM);
|
||||
|
||||
initial_size = size;
|
||||
notify_on_grow = bool(notify);
|
||||
@ -87,7 +87,7 @@ namespace vk
|
||||
|
||||
// Discard old heap and create a new one. Old heap will be garbage collected when no longer needed
|
||||
get_resource_manager()->dispose(heap);
|
||||
heap = std::make_unique<buffer>(*g_render_device, aligned_new_size, memory_index, memory_flags, usage, 0);
|
||||
heap = std::make_unique<buffer>(*g_render_device, aligned_new_size, memory_index, memory_flags, usage, 0, VMM_ALLOCATION_POOL_SYSTEM);
|
||||
|
||||
if (notify_on_grow)
|
||||
{
|
||||
|
@ -53,9 +53,9 @@ namespace vk
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags image_flags,
|
||||
vmm_allocation_pool allocation_pool,
|
||||
rsx::format_class format_class)
|
||||
: current_layout(initial_layout)
|
||||
, m_device(dev)
|
||||
: m_device(dev)
|
||||
{
|
||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
info.imageType = image_type;
|
||||
@ -70,23 +70,7 @@ namespace vk
|
||||
info.initialLayout = initial_layout;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
validate(dev, info);
|
||||
CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value));
|
||||
|
||||
VkMemoryRequirements memory_req;
|
||||
vkGetImageMemoryRequirements(m_device, value, &memory_req);
|
||||
|
||||
if (!(memory_req.memoryTypeBits & (1 << memory_type_index)))
|
||||
{
|
||||
//Suggested memory type is incompatible with this memory type.
|
||||
//Go through the bitset and test for requested props.
|
||||
if (!dev.get_compatible_memory_type(memory_req.memoryTypeBits, access_flags, &memory_type_index))
|
||||
fmt::throw_exception("No compatible memory type was found!");
|
||||
}
|
||||
|
||||
memory = std::make_shared<vk::memory_block>(m_device, memory_req.size, memory_req.alignment, memory_type_index);
|
||||
CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()));
|
||||
|
||||
create_impl(dev, access_flags, memory_type_index, allocation_pool);
|
||||
m_storage_aspect = get_aspect_flags(format);
|
||||
|
||||
if (format_class == RSX_FORMAT_CLASS_UNDEFINED)
|
||||
@ -111,6 +95,30 @@ namespace vk
|
||||
vkDestroyImage(m_device, value, nullptr);
|
||||
}
|
||||
|
||||
void image::create_impl(const vk::render_device& dev, u32 access_flags, u32 memory_type_index, vmm_allocation_pool allocation_pool)
|
||||
{
|
||||
ensure(!value && !memory);
|
||||
validate(dev, info);
|
||||
|
||||
CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value));
|
||||
|
||||
VkMemoryRequirements memory_req;
|
||||
vkGetImageMemoryRequirements(m_device, value, &memory_req);
|
||||
|
||||
if (!(memory_req.memoryTypeBits & (1 << memory_type_index)))
|
||||
{
|
||||
//Suggested memory type is incompatible with this memory type.
|
||||
//Go through the bitset and test for requested props.
|
||||
if (!dev.get_compatible_memory_type(memory_req.memoryTypeBits, access_flags, &memory_type_index))
|
||||
fmt::throw_exception("No compatible memory type was found!");
|
||||
}
|
||||
|
||||
memory = std::make_shared<vk::memory_block>(m_device, memory_req.size, memory_req.alignment, memory_type_index, allocation_pool);
|
||||
CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()));
|
||||
|
||||
current_layout = info.initialLayout;
|
||||
}
|
||||
|
||||
u32 image::width() const
|
||||
{
|
||||
return info.extent.width;
|
||||
@ -330,6 +338,20 @@ namespace vk
|
||||
#endif
|
||||
}
|
||||
|
||||
viewable_image* viewable_image::clone()
|
||||
{
|
||||
// Destructive cloning. The clone grabs the GPU objects owned by this instance.
|
||||
// This instance can be rebuilt in-place by calling create_impl() which will create a duplicate now owned by this.
|
||||
auto result = new viewable_image();
|
||||
result->m_device = this->m_device;
|
||||
result->info = this->info;
|
||||
result->value = this->value;
|
||||
result->memory = std::move(this->memory);
|
||||
result->views = std::move(this->views);
|
||||
this->value = VK_NULL_HANDLE;
|
||||
return result;
|
||||
}
|
||||
|
||||
image_view* viewable_image::get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap, VkImageAspectFlags mask)
|
||||
{
|
||||
if (remap_encoding == VK_REMAP_IDENTITY)
|
||||
|
@ -35,6 +35,10 @@ namespace vk
|
||||
|
||||
void validate(const vk::render_device& dev, const VkImageCreateInfo& info) const;
|
||||
|
||||
protected:
|
||||
image() = default;
|
||||
void create_impl(const vk::render_device& dev, u32 access_flags, u32 memory_type_index, vmm_allocation_pool allocation_pool);
|
||||
|
||||
public:
|
||||
VkImage value = VK_NULL_HANDLE;
|
||||
VkComponentMapping native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||
@ -55,6 +59,7 @@ namespace vk
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags image_flags,
|
||||
vmm_allocation_pool allocation_pool,
|
||||
rsx::format_class format_class = RSX_FORMAT_CLASS_UNDEFINED);
|
||||
|
||||
virtual ~image();
|
||||
@ -84,7 +89,7 @@ namespace vk
|
||||
// Debug utils
|
||||
void set_debug_name(const std::string& name);
|
||||
|
||||
private:
|
||||
protected:
|
||||
VkDevice m_device;
|
||||
};
|
||||
|
||||
@ -118,8 +123,9 @@ namespace vk
|
||||
|
||||
class viewable_image : public image
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
std::unordered_multimap<u32, std::unique_ptr<vk::image_view>> views;
|
||||
viewable_image* clone();
|
||||
|
||||
public:
|
||||
using image::image;
|
||||
|
@ -22,7 +22,10 @@ namespace vk
|
||||
allocatorInfo.physicalDevice = pdev;
|
||||
allocatorInfo.device = dev;
|
||||
|
||||
vmaCreateAllocator(&allocatorInfo, &m_allocator);
|
||||
CHECK_RESULT(vmaCreateAllocator(&allocatorInfo, &m_allocator));
|
||||
|
||||
// Allow fastest possible allocation on start
|
||||
set_fastest_allocation_flags();
|
||||
}
|
||||
|
||||
void mem_allocator_vma::destroy()
|
||||
@ -30,7 +33,7 @@ namespace vk
|
||||
vmaDestroyAllocator(m_allocator);
|
||||
}
|
||||
|
||||
mem_allocator_vk::mem_handle_t mem_allocator_vma::alloc(u64 block_sz, u64 alignment, u32 memory_type_index)
|
||||
mem_allocator_vk::mem_handle_t mem_allocator_vma::alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool)
|
||||
{
|
||||
VmaAllocation vma_alloc;
|
||||
VkMemoryRequirements mem_req = {};
|
||||
@ -40,7 +43,7 @@ namespace vk
|
||||
mem_req.size = ::align2(block_sz, alignment);
|
||||
mem_req.alignment = alignment;
|
||||
create_info.memoryTypeBits = 1u << memory_type_index;
|
||||
create_info.flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
|
||||
create_info.flags = m_allocation_flags;
|
||||
|
||||
if (VkResult result = vmaAllocateMemory(m_allocator, &mem_req, &create_info, &vma_alloc, nullptr);
|
||||
result != VK_SUCCESS)
|
||||
@ -62,7 +65,7 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
vmm_notify_memory_allocated(vma_alloc, memory_type_index, block_sz);
|
||||
vmm_notify_memory_allocated(vma_alloc, memory_type_index, block_sz, pool);
|
||||
return vma_alloc;
|
||||
}
|
||||
|
||||
@ -123,7 +126,17 @@ namespace vk
|
||||
return max_usage;
|
||||
}
|
||||
|
||||
mem_allocator_vk::mem_handle_t mem_allocator_vk::alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index)
|
||||
void mem_allocator_vma::set_safest_allocation_flags()
|
||||
{
|
||||
m_allocation_flags = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
|
||||
}
|
||||
|
||||
void mem_allocator_vma::set_fastest_allocation_flags()
|
||||
{
|
||||
m_allocation_flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
|
||||
}
|
||||
|
||||
mem_allocator_vk::mem_handle_t mem_allocator_vk::alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index, vmm_allocation_pool pool)
|
||||
{
|
||||
VkDeviceMemory memory;
|
||||
VkMemoryAllocateInfo info = {};
|
||||
@ -149,7 +162,7 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
vmm_notify_memory_allocated(memory, memory_type_index, block_sz);
|
||||
vmm_notify_memory_allocated(memory, memory_type_index, block_sz, pool);
|
||||
return memory;
|
||||
}
|
||||
|
||||
@ -191,11 +204,11 @@ namespace vk
|
||||
return g_render_device->get_allocator();
|
||||
}
|
||||
|
||||
memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index)
|
||||
: m_device(dev)
|
||||
memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool)
|
||||
: m_device(dev), m_size(block_sz)
|
||||
{
|
||||
m_mem_allocator = get_current_mem_allocator();
|
||||
m_mem_handle = m_mem_allocator->alloc(block_sz, alignment, memory_type_index);
|
||||
m_mem_handle = m_mem_allocator->alloc(block_sz, alignment, memory_type_index, pool);
|
||||
}
|
||||
|
||||
memory_block::~memory_block()
|
||||
@ -259,6 +272,11 @@ namespace vk
|
||||
return m_mem_allocator->get_vk_device_memory_offset(m_mem_handle);
|
||||
}
|
||||
|
||||
u64 memory_block::size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void* memory_block::map(u64 offset, u64 size)
|
||||
{
|
||||
return m_mem_allocator->map(m_mem_handle, offset, size);
|
||||
|
@ -8,17 +8,27 @@
|
||||
|
||||
namespace vk
|
||||
{
|
||||
enum vmm_allocation_pool
|
||||
{
|
||||
VMM_ALLOCATION_POOL_UNDEFINED = 0,
|
||||
VMM_ALLOCATION_POOL_SYSTEM,
|
||||
VMM_ALLOCATION_POOL_SURFACE_CACHE,
|
||||
VMM_ALLOCATION_POOL_TEXTURE_CACHE,
|
||||
VMM_ALLOCATION_POOL_SWAPCHAIN,
|
||||
VMM_ALLOCATION_POOL_SCRATCH,
|
||||
};
|
||||
|
||||
class mem_allocator_base
|
||||
{
|
||||
public:
|
||||
using mem_handle_t = void*;
|
||||
|
||||
mem_allocator_base(VkDevice dev, VkPhysicalDevice /*pdev*/) : m_device(dev) {}
|
||||
mem_allocator_base(VkDevice dev, VkPhysicalDevice /*pdev*/) : m_device(dev), m_allocation_flags(0) {}
|
||||
virtual ~mem_allocator_base() = default;
|
||||
|
||||
virtual void destroy() = 0;
|
||||
|
||||
virtual mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index) = 0;
|
||||
virtual mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) = 0;
|
||||
virtual void free(mem_handle_t mem_handle) = 0;
|
||||
virtual void* map(mem_handle_t mem_handle, u64 offset, u64 size) = 0;
|
||||
virtual void unmap(mem_handle_t mem_handle) = 0;
|
||||
@ -26,8 +36,12 @@ namespace vk
|
||||
virtual u64 get_vk_device_memory_offset(mem_handle_t mem_handle) = 0;
|
||||
virtual f32 get_memory_usage() = 0;
|
||||
|
||||
virtual void set_safest_allocation_flags() {}
|
||||
virtual void set_fastest_allocation_flags() {}
|
||||
|
||||
protected:
|
||||
VkDevice m_device;
|
||||
VkFlags m_allocation_flags;
|
||||
};
|
||||
|
||||
|
||||
@ -42,7 +56,7 @@ namespace vk
|
||||
|
||||
void destroy() override;
|
||||
|
||||
mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index) override;
|
||||
mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) override;
|
||||
|
||||
void free(mem_handle_t mem_handle) override;
|
||||
void* map(mem_handle_t mem_handle, u64 offset, u64 /*size*/) override;
|
||||
@ -52,6 +66,9 @@ namespace vk
|
||||
u64 get_vk_device_memory_offset(mem_handle_t mem_handle) override;
|
||||
f32 get_memory_usage() override;
|
||||
|
||||
void set_safest_allocation_flags() override;
|
||||
void set_fastest_allocation_flags() override;
|
||||
|
||||
private:
|
||||
VmaAllocator m_allocator;
|
||||
std::array<VmaBudget, VK_MAX_MEMORY_HEAPS> stats;
|
||||
@ -68,7 +85,7 @@ namespace vk
|
||||
|
||||
void destroy() override {}
|
||||
|
||||
mem_handle_t alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index) override;
|
||||
mem_handle_t alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index, vmm_allocation_pool pool) override;
|
||||
|
||||
void free(mem_handle_t mem_handle) override;
|
||||
void* map(mem_handle_t mem_handle, u64 offset, u64 size) override;
|
||||
@ -81,7 +98,7 @@ namespace vk
|
||||
|
||||
struct memory_block
|
||||
{
|
||||
memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index);
|
||||
memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool);
|
||||
virtual ~memory_block();
|
||||
|
||||
virtual VkDeviceMemory get_vk_device_memory();
|
||||
@ -90,6 +107,8 @@ namespace vk
|
||||
virtual void* map(u64 offset, u64 size);
|
||||
virtual void unmap();
|
||||
|
||||
u64 size() const;
|
||||
|
||||
memory_block(const memory_block&) = delete;
|
||||
memory_block(memory_block&&) = delete;
|
||||
|
||||
@ -100,6 +119,7 @@ namespace vk
|
||||
VkDevice m_device;
|
||||
vk::mem_allocator_base* m_mem_allocator = nullptr;
|
||||
mem_allocator_base::mem_handle_t m_mem_handle;
|
||||
u64 m_size;
|
||||
};
|
||||
|
||||
struct memory_block_host : public memory_block
|
||||
@ -122,11 +142,14 @@ namespace vk
|
||||
void* m_host_pointer;
|
||||
};
|
||||
|
||||
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size);
|
||||
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool);
|
||||
void vmm_notify_memory_freed(void* handle);
|
||||
void vmm_reset();
|
||||
void vmm_check_memory_usage();
|
||||
u64 vmm_get_application_memory_usage(u32 memory_type);
|
||||
u64 vmm_get_application_pool_usage(vmm_allocation_pool pool);
|
||||
bool vmm_handle_memory_pressure(rsx::problem_severity severity);
|
||||
rsx::problem_severity vmm_determine_memory_load_severity();
|
||||
|
||||
mem_allocator_base* get_current_mem_allocator();
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ namespace vk
|
||||
auto& tex = g_null_image_views[type];
|
||||
tex = std::make_unique<viewable_image>(*g_render_device, g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
image_type, VK_FORMAT_B8G8R8A8_UNORM, size, size, 1, 1, num_layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, flags);
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, flags, VMM_ALLOCATION_POOL_SCRATCH);
|
||||
|
||||
// Initialize memory to transparent black
|
||||
tex->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
@ -122,7 +122,7 @@ namespace vk
|
||||
|
||||
return new vk::image(*g_render_device, g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D, format, new_width, new_height, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0);
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_SCRATCH);
|
||||
};
|
||||
|
||||
const u32 key = (format_class << 24u) | format;
|
||||
@ -160,7 +160,7 @@ namespace vk
|
||||
|
||||
scratch_buffer = std::make_unique<vk::buffer>(*g_render_device, alloc_size,
|
||||
g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0);
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_SCRATCH);
|
||||
}
|
||||
|
||||
return scratch_buffer.get();
|
||||
|
@ -27,14 +27,14 @@ namespace vk
|
||||
swapchain_image_RPCS3(render_device& dev, const memory_type_mapping& memory_map, u32 width, u32 height)
|
||||
:image(dev, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_B8G8R8A8_UNORM, width, height, 1, 1, 1,
|
||||
VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0)
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, VMM_ALLOCATION_POOL_SWAPCHAIN)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
current_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
m_dma_buffer = std::make_unique<buffer>(dev, m_width * m_height * 4, memory_map.host_visible_coherent,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0);
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_SWAPCHAIN);
|
||||
}
|
||||
|
||||
void do_dma_transfer(command_buffer& cmd)
|
||||
|
@ -84,7 +84,8 @@ namespace vk
|
||||
dev.get_memory_mapping().host_visible_coherent,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
0
|
||||
0,
|
||||
VMM_ALLOCATION_POOL_SYSTEM
|
||||
);
|
||||
|
||||
m_value = reinterpret_cast<u32*>(m_buffer->map(0, 4));
|
||||
|
Loading…
x
Reference in New Issue
Block a user