rsx: Improve separate treatment of write exceptions vs read exceptions

- Optimizes search functionality and avoids thrashing valid sections
This commit is contained in:
kd-11 2017-10-24 13:59:46 +03:00
parent 5fc36d64b6
commit e9f293f522
5 changed files with 27 additions and 25 deletions

View file

@ -192,6 +192,7 @@ namespace rsx
std::vector<std::pair<section_storage_type*, ranged_storage*>> result;
u64 cache_tag = get_system_time();
u32 last_dirty_block = UINT32_MAX;
std::pair<u32, u32> trampled_range = std::make_pair(address, address + range);
for (auto It = m_cache.begin(); It != m_cache.end(); It++)
@ -250,7 +251,7 @@ namespace rsx
//2. A vector of all sections that should be flushed if the caller did not set the allow_flush method. That way the caller can make preparations on how to deal with sections that require flushing
// Note that the sections will be unlocked regardless of the allow_flush flag
template <typename ...Args>
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl_base(u32 address, u32 range, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras)
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl_base(u32 address, u32 range, bool is_writing, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras)
{
auto trampled_set = get_intersecting_set(address, range, allow_flush);
@ -260,6 +261,9 @@ namespace rsx
const auto to_reprotect = std::remove_if(trampled_set.begin(), trampled_set.end(),
[&](const std::pair<section_storage_type*, ranged_storage*>& obj)
{
if (!is_writing && obj.first->get_protection() != utils::protection::no)
return true;
if (!rebuild_cache && !obj.first->is_flushable())
return false;
@ -300,7 +304,10 @@ namespace rsx
obj.first->set_dirty(false);
}
trampled_set.erase(to_reprotect, trampled_set.end());
if (discard_only)
return{ true, {} };
//trampled_set.erase(to_reprotect, trampled_set.end());
if (allow_flush)
{
@ -324,9 +331,9 @@ namespace rsx
}
template <typename ...Args>
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl(u32 address, u32 range, bool discard, bool allow_flush, Args&&... extras)
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
{
return invalidate_range_impl_base(address, range, discard, false, allow_flush, std::forward<Args>(extras)...);
return invalidate_range_impl_base(address, range, is_writing, discard, false, allow_flush, std::forward<Args>(extras)...);
}
bool is_hw_blit_engine_compatible(const u32 format) const
@ -565,19 +572,13 @@ namespace rsx
}
template <typename ...Args>
std::pair<bool, std::vector<section_storage_type*>> invalidate_address(u32 address, bool allow_flush, Args&&... extras)
std::pair<bool, std::vector<section_storage_type*>> invalidate_address(u32 address, bool is_writing, bool allow_flush, Args&&... extras)
{
return invalidate_range(address, 4096 - (address & 4095), false, allow_flush, std::forward<Args>(extras)...);
return invalidate_range(address, 4096 - (address & 4095), is_writing, false, allow_flush, std::forward<Args>(extras)...);
}
template <typename ...Args>
std::pair<bool, std::vector<section_storage_type*>> flush_address(u32 address, Args&&... extras)
{
return invalidate_range(address, 4096 - (address & 4095), false, true, std::forward<Args>(extras)...);
}
template <typename ...Args>
std::pair<bool, std::vector<section_storage_type*>> invalidate_range(u32 address, u32 range, bool discard, bool allow_flush, Args&&... extras)
std::pair<bool, std::vector<section_storage_type*>> invalidate_range(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
{
std::pair<u32, u32> trampled_range = std::make_pair(address, address + range);
@ -591,7 +592,7 @@ namespace rsx
}
writer_lock lock(m_cache_mutex);
return invalidate_range_impl(address, range, discard, allow_flush, std::forward<Args>(extras)...);
return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward<Args>(extras)...);
}
template <typename ...Args>
@ -908,7 +909,7 @@ namespace rsx
auto subresources_layout = get_subresources_layout(tex);
auto remap_vector = tex.decoded_remap();
invalidate_range_impl(texaddr, tex_size, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(texaddr, tex_size, false, false, true, std::forward<Args>(extras)...);
m_texture_memory_in_use += (tex_pitch * tex_height);
return upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
@ -1001,8 +1002,8 @@ namespace rsx
const u32 memcpy_bytes_length = dst.clip_width * bpp * dst.clip_height;
lock.upgrade();
invalidate_range_impl(src_address, memcpy_bytes_length, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(dst_address, memcpy_bytes_length, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(src_address, memcpy_bytes_length, false, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(dst_address, memcpy_bytes_length, true, false, true, std::forward<Args>(extras)...);
memcpy(dst.pixels, src.pixels, memcpy_bytes_length);
return true;
}
@ -1104,7 +1105,7 @@ namespace rsx
{
lock.upgrade();
invalidate_range_impl(src_address, src.pitch * src.slice_h, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(src_address, src.pitch * src.slice_h, false, false, true, std::forward<Args>(extras)...);
const u16 pitch_in_block = src_is_argb8 ? src.pitch >> 2 : src.pitch >> 1;
std::vector<rsx_subresource_layout> subresource_layout;
@ -1176,7 +1177,7 @@ namespace rsx
if (format_mismatch)
{
lock.upgrade();
invalidate_range_impl(cached_dest->get_section_base(), cached_dest->get_section_size(), false, true, std::forward<Args>(extras)...);
invalidate_range_impl(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, true, std::forward<Args>(extras)...);
dest_texture = 0;
cached_dest = nullptr;
@ -1184,7 +1185,7 @@ namespace rsx
else if (invalidate_dst_range)
{
lock.upgrade();
invalidate_range_impl(dst_address, dst.pitch * dst.height, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(dst_address, dst.pitch * dst.height, true, false, true, std::forward<Args>(extras)...);
}
//Validate clipping region

View file

@ -1210,7 +1210,7 @@ u64 GLGSRender::timestamp() const
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
{
bool can_flush = (std::this_thread::get_id() == m_thread_id);
auto result = m_gl_texture_cache.invalidate_address(address, can_flush);
auto result = m_gl_texture_cache.invalidate_address(address, is_writing, can_flush);
if (!result.first)
return false;
@ -1235,7 +1235,7 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing)
void GLGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
{
//Discard all memory in that range without bothering with writeback (Force it for strict?)
if (std::get<0>(m_gl_texture_cache.invalidate_range(address_base, size, true, false)))
if (std::get<0>(m_gl_texture_cache.invalidate_range(address_base, size, true, true, false)))
m_gl_texture_cache.purge_dirty();
}

View file

@ -403,7 +403,7 @@ void GLGSRender::read_buffers()
}
else
{
m_gl_texture_cache.invalidate_range(texaddr, range, false, true);
m_gl_texture_cache.invalidate_range(texaddr, range, false, false, true);
std::unique_ptr<u8[]> buffer(new u8[pitch * height]);
color_buffer.read(buffer.get(), width, height, pitch);

View file

@ -473,6 +473,7 @@ namespace gl
glBindTexture(target, id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);

View file

@ -740,7 +740,7 @@ VKGSRender::~VKGSRender()
bool VKGSRender::on_access_violation(u32 address, bool is_writing)
{
std::lock_guard<std::mutex> lock(m_secondary_cb_guard);
auto result = m_texture_cache.invalidate_address(address, false, *m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
auto result = m_texture_cache.invalidate_address(address, is_writing, false, *m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
if (!result.first)
return false;
@ -831,7 +831,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
void VKGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
{
std::lock_guard<std::mutex> lock(m_secondary_cb_guard);
if (std::get<0>(m_texture_cache.invalidate_range(address_base, size, false, false,
if (std::get<0>(m_texture_cache.invalidate_range(address_base, size, true, true, false,
*m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue())))
{
m_texture_cache.purge_dirty();