rsx: Improve surface store resource management

- vk: Use frame testing to determine invalidated resources that can be safely deleted
This commit is contained in:
kd-11 2017-10-31 21:01:24 +03:00
parent ec3e5c547f
commit af1d3c2aa6
4 changed files with 38 additions and 2 deletions

View file

@ -165,8 +165,11 @@ namespace rsx
new_surface_storage = std::move(rtt); new_surface_storage = std::move(rtt);
if (old_surface) if (old_surface)
{
//Exchange this surface with the invalidated one //Exchange this surface with the invalidated one
Traits::notify_surface_invalidated(old_surface_storage);
rtt = std::move(old_surface_storage); rtt = std::move(old_surface_storage);
}
else else
//rtt is now empty - erase it //rtt is now empty - erase it
invalidated_resources.erase(It); invalidated_resources.erase(It);
@ -179,8 +182,11 @@ namespace rsx
} }
if (old_surface != nullptr && new_surface == nullptr) if (old_surface != nullptr && new_surface == nullptr)
{
//This was already determined to be invalid and is excluded from testing above //This was already determined to be invalid and is excluded from testing above
Traits::notify_surface_invalidated(old_surface_storage);
invalidated_resources.push_back(std::move(old_surface_storage)); invalidated_resources.push_back(std::move(old_surface_storage));
}
if (new_surface != nullptr) if (new_surface != nullptr)
{ {
@ -229,8 +235,11 @@ namespace rsx
new_surface_storage = std::move(ds); new_surface_storage = std::move(ds);
if (old_surface) if (old_surface)
{
//Exchange this surface with the invalidated one //Exchange this surface with the invalidated one
Traits::notify_surface_invalidated(old_surface_storage);
ds = std::move(old_surface_storage); ds = std::move(old_surface_storage);
}
else else
invalidated_resources.erase(It); invalidated_resources.erase(It);
@ -242,8 +251,11 @@ namespace rsx
} }
if (old_surface != nullptr && new_surface == nullptr) if (old_surface != nullptr && new_surface == nullptr)
{
//This was already determined to be invalid and is excluded from testing above //This was already determined to be invalid and is excluded from testing above
Traits::notify_surface_invalidated(old_surface_storage);
invalidated_resources.push_back(std::move(old_surface_storage)); invalidated_resources.push_back(std::move(old_surface_storage));
}
if (new_surface != nullptr) if (new_surface != nullptr)
{ {
@ -498,6 +510,7 @@ namespace rsx
if (surface == ref) if (surface == ref)
{ {
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second)); invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It); m_render_targets_storage.erase(It);
@ -515,6 +528,7 @@ namespace rsx
if (surface == ref) if (surface == ref)
{ {
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second)); invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It); m_depth_stencil_storage.erase(It);
@ -541,6 +555,7 @@ namespace rsx
auto It = m_render_targets_storage.find(addr); auto It = m_render_targets_storage.find(addr);
if (It != m_render_targets_storage.end()) if (It != m_render_targets_storage.end())
{ {
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second)); invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It); m_render_targets_storage.erase(It);
@ -553,6 +568,7 @@ namespace rsx
auto It = m_depth_stencil_storage.find(addr); auto It = m_depth_stencil_storage.find(addr);
if (It != m_depth_stencil_storage.end()) if (It != m_depth_stencil_storage.end())
{ {
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second)); invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It); m_depth_stencil_storage.erase(It);

View file

@ -142,6 +142,9 @@ struct render_target_traits
//TODO //TODO
} }
static
void notify_surface_invalidated(const ComPtr<ID3D12Resource>&)
{}
static static
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false) bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false)

View file

@ -253,6 +253,10 @@ struct gl_render_target_traits
static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); } static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); }
static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); } static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); }
static
void notify_surface_invalidated(const std::unique_ptr<gl::render_target>&)
{}
static static
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false) bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false)
{ {

View file

@ -26,6 +26,7 @@ namespace vk
std::unique_ptr<vk::image_view> view; std::unique_ptr<vk::image_view> view;
render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
render_target(vk::render_device &dev, render_target(vk::render_device &dev,
uint32_t memory_type_index, uint32_t memory_type_index,
@ -223,6 +224,7 @@ namespace rsx
//Reset deref count //Reset deref count
surface->deref_count = 0; surface->deref_count = 0;
surface->frame_tag = 0;
} }
static void prepare_rtt_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface) static void prepare_rtt_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
@ -238,6 +240,7 @@ namespace rsx
//Reset deref count //Reset deref count
surface->deref_count = 0; surface->deref_count = 0;
surface->frame_tag = 0;
} }
static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface) static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
@ -261,6 +264,12 @@ namespace rsx
ds->old_contents = old_surface; ds->old_contents = old_surface;
} }
static
void notify_surface_invalidated(const std::unique_ptr<vk::render_target> &surface)
{
surface->frame_tag = vk::get_current_frame_id();
}
static bool rtt_has_format_width_height(const std::unique_ptr<vk::render_target> &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false) static bool rtt_has_format_width_height(const std::unique_ptr<vk::render_target> &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false)
{ {
if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy' if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy'
@ -337,9 +346,13 @@ namespace rsx
void free_invalidated() void free_invalidated()
{ {
invalidated_resources.remove_if([](std::unique_ptr<vk::render_target> &rtt) const u64 last_finished_frame = vk::get_last_completed_frame_id();
invalidated_resources.remove_if([&](std::unique_ptr<vk::render_target> &rtt)
{ {
if (rtt->deref_count >= 2) return true; verify(HERE), rtt->frame_tag != 0;
if (rtt->deref_count >= 2 && rtt->frame_tag < last_finished_frame)
return true;
rtt->deref_count++; rtt->deref_count++;
return false; return false;