rsx: Tag cache blocks returned on access violation to validate data passed

to flush_all is up to date. Should prevent recursive exceptions

Partially revert Jarves' fix to invalidate cache on tile unbind. This will
need alot more work. Fixes hangs
This commit is contained in:
kd-11 2017-10-28 22:17:27 +03:00
parent 395b4bfa45
commit 361e80f7dc
5 changed files with 85 additions and 33 deletions

View file

@ -6,6 +6,8 @@
#include <atomic> #include <atomic>
extern u64 get_system_time();
namespace rsx namespace rsx
{ {
enum texture_create_flags enum texture_create_flags
@ -156,6 +158,8 @@ namespace rsx
shared_mutex m_cache_mutex; shared_mutex m_cache_mutex;
std::unordered_map<u32, ranged_storage> m_cache; std::unordered_map<u32, ranged_storage> m_cache;
std::atomic<u64> m_cache_update_tag = {};
std::pair<u32, u32> read_only_range = std::make_pair(0xFFFFFFFF, 0); std::pair<u32, u32> read_only_range = std::make_pair(0xFFFFFFFF, 0);
std::pair<u32, u32> no_access_range = std::make_pair(0xFFFFFFFF, 0); std::pair<u32, u32> no_access_range = std::make_pair(0xFFFFFFFF, 0);
@ -183,6 +187,11 @@ namespace rsx
constexpr u32 get_block_size() const { return 0x1000000; } constexpr u32 get_block_size() const { return 0x1000000; }
inline u32 get_block_address(u32 address) const { return (address & ~0xFFFFFF); } inline u32 get_block_address(u32 address) const { return (address & ~0xFFFFFF); }
inline void update_cache_tag()
{
m_cache_update_tag = get_system_time();
}
public: public:
//Struct to hold data on sections to be paged back onto cpu memory //Struct to hold data on sections to be paged back onto cpu memory
struct thrashed_set struct thrashed_set
@ -190,6 +199,9 @@ namespace rsx
bool violation_handled = false; bool violation_handled = false;
std::vector<section_storage_type*> affected_sections; //Always laid out with flushable sections first then other affected sections last std::vector<section_storage_type*> affected_sections; //Always laid out with flushable sections first then other affected sections last
int num_flushable = 0; int num_flushable = 0;
u64 cache_tag = 0;
u32 address_base = 0;
u32 address_range = 0;
}; };
private: private:
@ -368,6 +380,9 @@ namespace rsx
{ {
result.num_flushable = static_cast<int>(sections_to_flush.size()); result.num_flushable = static_cast<int>(sections_to_flush.size());
result.affected_sections = std::move(sections_to_flush); result.affected_sections = std::move(sections_to_flush);
result.address_base = address;
result.address_range = range;
result.cache_tag = m_cache_update_tag.load(std::memory_order_consume);
} }
for (auto It = to_reprotect; It != trampled_set.end(); It++) for (auto It = to_reprotect; It != trampled_set.end(); It++)
@ -392,12 +407,6 @@ namespace rsx
return {}; return {};
} }
template <typename ...Args>
thrashed_set invalidate_range_impl(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
{
return invalidate_range_impl_base(address, range, is_writing, discard, true, allow_flush, std::forward<Args>(extras)...);
}
bool is_hw_blit_engine_compatible(const u32 format) const bool is_hw_blit_engine_compatible(const u32 format) const
{ {
switch (format) switch (format)
@ -546,6 +555,7 @@ namespace rsx
region.protect(utils::protection::no); region.protect(utils::protection::no);
region.create(width, height, 1, 1, nullptr, image, pitch, false, std::forward<Args>(extras)...); region.create(width, height, 1, 1, nullptr, image, pitch, false, std::forward<Args>(extras)...);
region.set_context(texture_upload_context::framebuffer_storage); region.set_context(texture_upload_context::framebuffer_storage);
update_cache_tag();
} }
template <typename ...Args> template <typename ...Args>
@ -636,7 +646,13 @@ namespace rsx
template <typename ...Args> template <typename ...Args>
thrashed_set invalidate_address(u32 address, bool is_writing, bool allow_flush, Args&&... extras) thrashed_set invalidate_address(u32 address, bool is_writing, bool allow_flush, Args&&... extras)
{ {
return invalidate_range(address, 4096 - (address & 4095), is_writing, false, allow_flush, std::forward<Args>(extras)...); //Test before trying to acquire the lock
const auto range = 4096 - (address & 4095);
if (!region_intersects_cache(address, range, is_writing))
return{};
writer_lock lock(m_cache_mutex);
return invalidate_range_impl_base(address, range, is_writing, false, true, allow_flush, std::forward<Args>(extras)...);
} }
template <typename ...Args> template <typename ...Args>
@ -647,7 +663,7 @@ namespace rsx
return {}; return {};
writer_lock lock(m_cache_mutex); writer_lock lock(m_cache_mutex);
return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward<Args>(extras)...); return invalidate_range_impl_base(address, range, is_writing, discard, false, allow_flush, std::forward<Args>(extras)...);
} }
template <typename ...Args> template <typename ...Args>
@ -655,6 +671,8 @@ namespace rsx
{ {
writer_lock lock(m_cache_mutex); writer_lock lock(m_cache_mutex);
if (data.cache_tag == m_cache_update_tag.load(std::memory_order_consume))
{
std::vector<utils::protection> old_protections; std::vector<utils::protection> old_protections;
for (int n = data.num_flushable; n < data.affected_sections.size(); ++n) for (int n = data.num_flushable; n < data.affected_sections.size(); ++n)
{ {
@ -679,6 +697,30 @@ namespace rsx
data.affected_sections[n]->protect(old_protections[i++]); data.affected_sections[n]->protect(old_protections[i++]);
} }
} }
}
else
{
//The cache contents have changed between the two readings. This means the data held is useless
//Restore memory protection for the scan to work properly
for (int n = 0; n < data.num_flushable; n++)
{
if (data.affected_sections[n]->get_protection() == utils::protection::rw)
{
const u32 address = data.affected_sections[n]->get_section_base();
const u32 size = data.affected_sections[n]->get_section_size();
data.affected_sections[n]->protect(utils::protection::no);
m_cache[get_block_address(address)].notify(address, size);
}
else
{
LOG_WARNING(RSX, "Texture Cache: Section at address 0x%X was lost", data.affected_sections[n]->get_section_base());
}
}
update_cache_tag();
invalidate_range_impl_base(data.address_base, data.address_range, true, false, true, true, std::forward<Args>(extras)...);
}
return true; return true;
} }
@ -1080,8 +1122,8 @@ namespace rsx
const u32 memcpy_bytes_length = dst.clip_width * bpp * dst.clip_height; const u32 memcpy_bytes_length = dst.clip_width * bpp * dst.clip_height;
lock.upgrade(); lock.upgrade();
invalidate_range_impl(src_address, memcpy_bytes_length, false, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(src_address, memcpy_bytes_length, false, false, false, true, std::forward<Args>(extras)...);
invalidate_range_impl(dst_address, memcpy_bytes_length, true, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(dst_address, memcpy_bytes_length, true, false, false, true, std::forward<Args>(extras)...);
memcpy(dst.pixels, src.pixels, memcpy_bytes_length); memcpy(dst.pixels, src.pixels, memcpy_bytes_length);
return true; return true;
} }
@ -1188,7 +1230,7 @@ namespace rsx
{ {
lock.upgrade(); lock.upgrade();
invalidate_range_impl(src_address, src.pitch * src.slice_h, false, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(src_address, src.pitch * src.slice_h, false, false, false, true, std::forward<Args>(extras)...);
const u16 pitch_in_block = src_is_argb8 ? src.pitch >> 2 : src.pitch >> 1; const u16 pitch_in_block = src_is_argb8 ? src.pitch >> 2 : src.pitch >> 1;
std::vector<rsx_subresource_layout> subresource_layout; std::vector<rsx_subresource_layout> subresource_layout;
@ -1260,7 +1302,7 @@ namespace rsx
if (format_mismatch) if (format_mismatch)
{ {
lock.upgrade(); lock.upgrade();
invalidate_range_impl(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, false, true, std::forward<Args>(extras)...);
dest_texture = 0; dest_texture = 0;
cached_dest = nullptr; cached_dest = nullptr;
@ -1268,7 +1310,7 @@ namespace rsx
else if (invalidate_dst_range) else if (invalidate_dst_range)
{ {
lock.upgrade(); lock.upgrade();
invalidate_range_impl(dst_address, dst.pitch * dst.height, true, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(dst_address, dst.pitch * dst.height, true, false, false, true, std::forward<Args>(extras)...);
} }
//Validate clipping region //Validate clipping region

View file

@ -1296,8 +1296,10 @@ bool GLGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
void GLGSRender::notify_tile_unbound(u32 tile) void GLGSRender::notify_tile_unbound(u32 tile)
{ {
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); //TODO: Handle texture writeback
m_rtts.invalidate_surface_address(addr, false); //u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
//on_notify_memory_unmapped(addr, tiles[tile].size);
//m_rtts.invalidate_surface_address(addr, false);
} }
void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read) void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read)

View file

@ -673,7 +673,10 @@ namespace gl
//Its not necessary to lock blit dst textures as they are just reused as necessary //Its not necessary to lock blit dst textures as they are just reused as necessary
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode) if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
{
cached.protect(utils::protection::ro); cached.protect(utils::protection::ro);
update_cache_tag();
}
return &cached; return &cached;
} }

View file

@ -2716,6 +2716,8 @@ bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
void VKGSRender::notify_tile_unbound(u32 tile) void VKGSRender::notify_tile_unbound(u32 tile)
{ {
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); //TODO: Handle texture writeback
m_rtts.invalidate_surface_address(addr, false); //u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
//on_notify_memory_unmapped(addr, tiles[tile].size);
//m_rtts.invalidate_surface_address(addr, false);
} }

View file

@ -547,7 +547,10 @@ namespace vk
//Its not necessary to lock blit dst textures as they are just reused as necessary //Its not necessary to lock blit dst textures as they are just reused as necessary
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode) if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
{
region.protect(utils::protection::ro); region.protect(utils::protection::ro);
update_cache_tag();
}
read_only_range = region.get_min_max(read_only_range); read_only_range = region.get_min_max(read_only_range);
return &region; return &region;