mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 00:40:11 +00:00
vk: Refactor surface cache by moving code to cpp file
This commit is contained in:
parent
2ffa8f4623
commit
000414c47d
@ -1075,14 +1075,24 @@ namespace rsx
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
else if (m_active_memory_used > (max_safe_memory * 3) / 2)
|
||||
{
|
||||
rsx_log.warning("Surface cache is using too much memory! (%dM)", m_active_memory_used / 0x100000);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rsx_log.trace("Surface cache is using too much memory! (%dM)", m_active_memory_used / 0x100000);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool handle_memory_pressure(command_list_type cmd, problem_severity /*severity*/)
|
||||
virtual bool can_collapse_surface(const surface_storage_type&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool handle_memory_pressure(command_list_type cmd, problem_severity severity)
|
||||
{
|
||||
auto process_list_function = [&](std::unordered_map<u32, surface_storage_type>& data)
|
||||
{
|
||||
@ -1092,18 +1102,22 @@ namespace rsx
|
||||
if (surface->dirty())
|
||||
{
|
||||
// Force memory barrier to release some resources
|
||||
surface->memory_barrier(cmd, rsx::surface_access::shader_read);
|
||||
if (can_collapse_surface(It->second))
|
||||
{
|
||||
// NOTE: Do not call memory_barrier under fatal conditions as it can create allocations!
|
||||
// It would be safer to leave the resources hanging around and spill them instead
|
||||
surface->memory_barrier(cmd, rsx::surface_access::memory_read);
|
||||
}
|
||||
}
|
||||
else if (!surface->test())
|
||||
{
|
||||
// Remove this
|
||||
invalidate(It->second);
|
||||
It = data.erase(It);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
++It;
|
||||
}
|
||||
|
||||
++It;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,128 @@
|
||||
#include "VKRenderTargets.h"
|
||||
#include "VKResourceManager.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
void surface_cache::destroy()
|
||||
{
|
||||
invalidate_all();
|
||||
invalidated_resources.clear();
|
||||
}
|
||||
|
||||
u64 surface_cache::get_surface_cache_memory_quota(u64 total_device_memory)
|
||||
{
|
||||
total_device_memory /= 0x100000;
|
||||
u64 quota = 0;
|
||||
|
||||
if (total_device_memory >= 2048)
|
||||
{
|
||||
quota = std::min(6144ull, (total_device_memory * 40) / 100);
|
||||
}
|
||||
else if (total_device_memory >= 1024)
|
||||
{
|
||||
quota = 768;
|
||||
}
|
||||
else if (total_device_memory >= 768)
|
||||
{
|
||||
quota = 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove upto 128MB but at least aim for half of available VRAM
|
||||
quota = std::min(128ull, total_device_memory / 2);
|
||||
}
|
||||
|
||||
return quota * 0x100000;
|
||||
}
|
||||
|
||||
bool surface_cache::can_collapse_surface(const std::unique_ptr<vk::render_target>& surface)
|
||||
{
|
||||
if (surface->samples() == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// MSAA surface, check if we have the memory for this...
|
||||
return vk::vmm_determine_memory_load_severity() < rsx::problem_severity::fatal;
|
||||
}
|
||||
|
||||
bool surface_cache::handle_memory_pressure(vk::command_buffer& cmd, rsx::problem_severity severity)
|
||||
{
|
||||
bool any_released = rsx::surface_store<surface_cache_traits>::handle_memory_pressure(cmd, severity);
|
||||
|
||||
if (severity >= rsx::problem_severity::fatal)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
return any_released;
|
||||
}
|
||||
|
||||
void surface_cache::free_invalidated(vk::command_buffer& cmd, rsx::problem_severity memory_pressure)
|
||||
{
|
||||
// Do not allow more than 300M of RSX memory to be used by RTTs.
|
||||
// The actual boundary is 256M but we need to give some overallocation for performance reasons.
|
||||
if (check_memory_usage(300 * 0x100000))
|
||||
{
|
||||
if (!cmd.is_recording())
|
||||
{
|
||||
cmd.begin();
|
||||
}
|
||||
|
||||
const auto severity = std::max(memory_pressure, rsx::problem_severity::moderate);
|
||||
handle_memory_pressure(cmd, severity);
|
||||
}
|
||||
|
||||
const u64 last_finished_frame = vk::get_last_completed_frame_id();
|
||||
invalidated_resources.remove_if([&](std::unique_ptr<vk::render_target>& rtt)
|
||||
{
|
||||
ensure(rtt->frame_tag != 0);
|
||||
|
||||
if (rtt->has_refs())
|
||||
{
|
||||
// Actively in use, likely for a reading pass.
|
||||
// Call handle_memory_pressure before calling this method.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memory_pressure >= rsx::problem_severity::severe)
|
||||
{
|
||||
if (rtt->resolve_surface)
|
||||
{
|
||||
// We do not need to keep resolve targets around if things are bad.
|
||||
vk::get_resource_manager()->dispose(rtt->resolve_surface);
|
||||
}
|
||||
}
|
||||
|
||||
if (rtt->frame_tag >= last_finished_frame)
|
||||
{
|
||||
// RTT itself still in use by the frame.
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (memory_pressure)
|
||||
{
|
||||
case rsx::problem_severity::low:
|
||||
return (rtt->unused_check_count() >= 2);
|
||||
case rsx::problem_severity::moderate:
|
||||
return (rtt->unused_check_count() >= 1);
|
||||
case rsx::problem_severity::severe:
|
||||
case rsx::problem_severity::fatal:
|
||||
// We're almost dead anyway. Remove forcefully.
|
||||
return true;
|
||||
default:
|
||||
fmt::throw_exception("Unreachable");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool surface_cache::is_overallocated()
|
||||
{
|
||||
const auto surface_cache_vram_load = vmm_get_application_pool_usage(VMM_ALLOCATION_POOL_SURFACE_CACHE);
|
||||
const auto surface_cache_allocation_quota = get_surface_cache_memory_quota(get_current_renderer()->get_memory_mapping().device_local_total_bytes);
|
||||
return (surface_cache_vram_load > surface_cache_allocation_quota);
|
||||
}
|
||||
|
||||
// Get the linear resolve target bound to this surface. Initialize if none exists
|
||||
vk::viewable_image* render_target::get_resolve_target_safe(vk::command_buffer& cmd)
|
||||
{
|
||||
|
@ -6,10 +6,10 @@
|
||||
#include "VKFormats.h"
|
||||
#include "VKHelpers.h"
|
||||
#include "vkutils/barriers.h"
|
||||
#include "vkutils/buffer_object.h"
|
||||
#include "vkutils/data_heap.h"
|
||||
#include "vkutils/device.h"
|
||||
#include "vkutils/image.h"
|
||||
#include "vkutils/memory.h"
|
||||
#include "vkutils/scratch.h"
|
||||
|
||||
#include <span>
|
||||
@ -42,6 +42,7 @@ namespace vk
|
||||
|
||||
public:
|
||||
u64 frame_tag = 0; // frame id when invalidated, 0 if not invalid
|
||||
|
||||
using viewable_image::viewable_image;
|
||||
|
||||
vk::viewable_image* get_surface(rsx::surface_access access_type) override;
|
||||
@ -78,7 +79,7 @@ namespace vk
|
||||
rsx::surface_color_format format,
|
||||
usz width, usz height, usz pitch,
|
||||
rsx::surface_antialiasing antialias,
|
||||
vk::render_device &device, vk::command_buffer& cmd)
|
||||
vk::render_device& device, vk::command_buffer& cmd)
|
||||
{
|
||||
const auto fmt = vk::get_compatible_surface_format(format);
|
||||
VkFormat requested_format = fmt.first;
|
||||
@ -118,7 +119,7 @@ namespace vk
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, RSX_FORMAT_CLASS_COLOR);
|
||||
0, 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);
|
||||
@ -144,7 +145,7 @@ namespace vk
|
||||
rsx::surface_depth_format2 format,
|
||||
usz width, usz height, usz pitch,
|
||||
rsx::surface_antialiasing antialias,
|
||||
vk::render_device &device, vk::command_buffer& cmd)
|
||||
vk::render_device& device, vk::command_buffer& cmd)
|
||||
{
|
||||
const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format);
|
||||
VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
@ -179,7 +180,7 @@ namespace vk
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, rsx::classify_format(format));
|
||||
0, 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);
|
||||
@ -187,7 +188,7 @@ namespace vk
|
||||
ds->set_format(format);
|
||||
ds->set_aa_mode(antialias);
|
||||
ds->sample_layout = sample_layout;
|
||||
ds->memory_usage_flags= rsx::surface_usage_flags::attachment;
|
||||
ds->memory_usage_flags = rsx::surface_usage_flags::attachment;
|
||||
ds->state_flags = rsx::surface_state_flags::erase_bkgnd;
|
||||
ds->native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R };
|
||||
ds->native_pitch = static_cast<u16>(width) * get_format_block_size_in_bytes(format) * ds->samples_x;
|
||||
@ -221,7 +222,7 @@ namespace vk
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
ref->info.usage,
|
||||
ref->info.flags,
|
||||
vk::VMM_ALLOCATION_POOL_SURFACE_CACHE,
|
||||
VMM_ALLOCATION_POOL_SURFACE_CACHE,
|
||||
ref->format_class());
|
||||
|
||||
sink->add_ref();
|
||||
@ -274,7 +275,7 @@ namespace vk
|
||||
surface->get_surface_height() >= height);
|
||||
}
|
||||
|
||||
static void prepare_surface_for_drawing(vk::command_buffer& cmd, vk::render_target *surface)
|
||||
static void prepare_surface_for_drawing(vk::command_buffer& cmd, vk::render_target* surface)
|
||||
{
|
||||
if (surface->aspect() == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
{
|
||||
@ -292,12 +293,12 @@ namespace vk
|
||||
static void prepare_surface_for_sampling(vk::command_buffer& /*cmd*/, vk::render_target* /*surface*/)
|
||||
{}
|
||||
|
||||
static bool surface_is_pitch_compatible(const std::unique_ptr<vk::render_target> &surface, usz pitch)
|
||||
static bool surface_is_pitch_compatible(const std::unique_ptr<vk::render_target>& surface, usz pitch)
|
||||
{
|
||||
return surface->rsx_pitch == pitch;
|
||||
}
|
||||
|
||||
static void invalidate_surface_contents(vk::command_buffer& /*cmd*/, vk::render_target *surface, u32 address, usz pitch)
|
||||
static void invalidate_surface_contents(vk::command_buffer& /*cmd*/, vk::render_target* surface, u32 address, usz pitch)
|
||||
{
|
||||
surface->rsx_pitch = static_cast<u16>(pitch);
|
||||
surface->queue_tag(address);
|
||||
@ -307,7 +308,7 @@ namespace vk
|
||||
surface->raster_type = rsx::surface_raster_type::linear;
|
||||
}
|
||||
|
||||
static void notify_surface_invalidated(const std::unique_ptr<vk::render_target> &surface)
|
||||
static void notify_surface_invalidated(const std::unique_ptr<vk::render_target>& surface)
|
||||
{
|
||||
surface->frame_tag = vk::get_current_frame_id();
|
||||
if (!surface->frame_tag) surface->frame_tag = 1;
|
||||
@ -324,14 +325,14 @@ namespace vk
|
||||
static void notify_surface_persist(const std::unique_ptr<vk::render_target>& /*surface*/)
|
||||
{}
|
||||
|
||||
static void notify_surface_reused(const std::unique_ptr<vk::render_target> &surface)
|
||||
static void notify_surface_reused(const std::unique_ptr<vk::render_target>& surface)
|
||||
{
|
||||
surface->state_flags |= rsx::surface_state_flags::erase_bkgnd;
|
||||
surface->add_ref();
|
||||
}
|
||||
|
||||
static bool int_surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
const std::unique_ptr<vk::render_target>& surface,
|
||||
VkFormat format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
@ -349,7 +350,7 @@ namespace vk
|
||||
}
|
||||
|
||||
static bool surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
const std::unique_ptr<vk::render_target>& surface,
|
||||
rsx::surface_color_format format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
@ -360,7 +361,7 @@ namespace vk
|
||||
}
|
||||
|
||||
static bool surface_matches_properties(
|
||||
const std::unique_ptr<vk::render_target> &surface,
|
||||
const std::unique_ptr<vk::render_target>& surface,
|
||||
rsx::surface_depth_format2 format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
@ -371,43 +372,22 @@ namespace vk
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs);
|
||||
}
|
||||
|
||||
static vk::render_target *get(const std::unique_ptr<vk::render_target> &tex)
|
||||
static vk::render_target* get(const std::unique_ptr<vk::render_target>& tex)
|
||||
{
|
||||
return tex.get();
|
||||
}
|
||||
};
|
||||
|
||||
struct surface_cache : public rsx::surface_store<vk::surface_cache_traits>
|
||||
class surface_cache : public rsx::surface_store<vk::surface_cache_traits>
|
||||
{
|
||||
void destroy()
|
||||
{
|
||||
invalidate_all();
|
||||
invalidated_resources.clear();
|
||||
}
|
||||
private:
|
||||
u64 get_surface_cache_memory_quota(u64 total_device_memory);
|
||||
|
||||
void free_invalidated(vk::command_buffer& cmd)
|
||||
{
|
||||
// Do not allow more than 256M of RSX memory to be used by RTTs
|
||||
if (check_memory_usage(256 * 0x100000))
|
||||
{
|
||||
if (!cmd.is_recording())
|
||||
{
|
||||
cmd.begin();
|
||||
}
|
||||
|
||||
handle_memory_pressure(cmd, rsx::problem_severity::moderate);
|
||||
}
|
||||
|
||||
const u64 last_finished_frame = vk::get_last_completed_frame_id();
|
||||
invalidated_resources.remove_if([&](std::unique_ptr<vk::render_target> &rtt)
|
||||
{
|
||||
ensure(rtt->frame_tag != 0);
|
||||
|
||||
if (rtt->unused_check_count() >= 2 && rtt->frame_tag < last_finished_frame)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
public:
|
||||
void destroy();
|
||||
bool is_overallocated();
|
||||
bool can_collapse_surface(const std::unique_ptr<vk::render_target>& surface) override;
|
||||
bool handle_memory_pressure(vk::command_buffer& cmd, rsx::problem_severity severity) override;
|
||||
void free_invalidated(vk::command_buffer& cmd, rsx::problem_severity memory_pressure);
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user