mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
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:
parent
395b4bfa45
commit
361e80f7dc
5 changed files with 85 additions and 33 deletions
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <atomic>
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
enum texture_create_flags
|
||||
|
@ -156,6 +158,8 @@ namespace rsx
|
|||
shared_mutex m_cache_mutex;
|
||||
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> no_access_range = std::make_pair(0xFFFFFFFF, 0);
|
||||
|
||||
|
@ -183,6 +187,11 @@ namespace rsx
|
|||
constexpr u32 get_block_size() const { return 0x1000000; }
|
||||
inline u32 get_block_address(u32 address) const { return (address & ~0xFFFFFF); }
|
||||
|
||||
inline void update_cache_tag()
|
||||
{
|
||||
m_cache_update_tag = get_system_time();
|
||||
}
|
||||
|
||||
public:
|
||||
//Struct to hold data on sections to be paged back onto cpu memory
|
||||
struct thrashed_set
|
||||
|
@ -190,6 +199,9 @@ namespace rsx
|
|||
bool violation_handled = false;
|
||||
std::vector<section_storage_type*> affected_sections; //Always laid out with flushable sections first then other affected sections last
|
||||
int num_flushable = 0;
|
||||
u64 cache_tag = 0;
|
||||
u32 address_base = 0;
|
||||
u32 address_range = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -368,6 +380,9 @@ namespace rsx
|
|||
{
|
||||
result.num_flushable = static_cast<int>(sections_to_flush.size());
|
||||
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++)
|
||||
|
@ -392,12 +407,6 @@ namespace rsx
|
|||
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
|
||||
{
|
||||
switch (format)
|
||||
|
@ -546,6 +555,7 @@ namespace rsx
|
|||
region.protect(utils::protection::no);
|
||||
region.create(width, height, 1, 1, nullptr, image, pitch, false, std::forward<Args>(extras)...);
|
||||
region.set_context(texture_upload_context::framebuffer_storage);
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
|
@ -636,7 +646,13 @@ namespace rsx
|
|||
template <typename ...Args>
|
||||
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>
|
||||
|
@ -647,7 +663,7 @@ namespace rsx
|
|||
return {};
|
||||
|
||||
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>
|
||||
|
@ -655,29 +671,55 @@ namespace rsx
|
|||
{
|
||||
writer_lock lock(m_cache_mutex);
|
||||
|
||||
std::vector<utils::protection> old_protections;
|
||||
for (int n = data.num_flushable; n < data.affected_sections.size(); ++n)
|
||||
if (data.cache_tag == m_cache_update_tag.load(std::memory_order_consume))
|
||||
{
|
||||
old_protections.push_back(data.affected_sections[n]->get_protection());
|
||||
data.affected_sections[n]->unprotect();
|
||||
}
|
||||
|
||||
for (int n = 0, i = 0; n < data.affected_sections.size(); ++n)
|
||||
{
|
||||
if (n < data.num_flushable)
|
||||
std::vector<utils::protection> old_protections;
|
||||
for (int n = data.num_flushable; n < data.affected_sections.size(); ++n)
|
||||
{
|
||||
if (!data.affected_sections[n]->flush(std::forward<Args>(extras)...))
|
||||
old_protections.push_back(data.affected_sections[n]->get_protection());
|
||||
data.affected_sections[n]->unprotect();
|
||||
}
|
||||
|
||||
for (int n = 0, i = 0; n < data.affected_sections.size(); ++n)
|
||||
{
|
||||
if (n < data.num_flushable)
|
||||
{
|
||||
//Missed address, note this
|
||||
//TODO: Lower severity when successful to keep the cache from overworking
|
||||
record_cache_miss(*data.affected_sections[n]);
|
||||
if (!data.affected_sections[n]->flush(std::forward<Args>(extras)...))
|
||||
{
|
||||
//Missed address, note this
|
||||
//TODO: Lower severity when successful to keep the cache from overworking
|
||||
record_cache_miss(*data.affected_sections[n]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Restore protection on the remaining sections
|
||||
data.affected_sections[n]->protect(old_protections[i++]);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
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++)
|
||||
{
|
||||
//Restore protection on the remaining sections
|
||||
data.affected_sections[n]->protect(old_protections[i++]);
|
||||
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;
|
||||
|
@ -1080,8 +1122,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, 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(src_address, memcpy_bytes_length, false, false, 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);
|
||||
return true;
|
||||
}
|
||||
|
@ -1188,7 +1230,7 @@ namespace rsx
|
|||
{
|
||||
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;
|
||||
std::vector<rsx_subresource_layout> subresource_layout;
|
||||
|
@ -1260,7 +1302,7 @@ namespace rsx
|
|||
if (format_mismatch)
|
||||
{
|
||||
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;
|
||||
cached_dest = nullptr;
|
||||
|
@ -1268,7 +1310,7 @@ namespace rsx
|
|||
else if (invalidate_dst_range)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
|
||||
m_rtts.invalidate_surface_address(addr, false);
|
||||
//TODO: Handle texture writeback
|
||||
//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)
|
||||
|
|
|
@ -673,7 +673,10 @@ namespace gl
|
|||
|
||||
//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)
|
||||
{
|
||||
cached.protect(utils::protection::ro);
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
return &cached;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
|
||||
m_rtts.invalidate_surface_address(addr, false);
|
||||
//TODO: Handle texture writeback
|
||||
//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);
|
||||
}
|
|
@ -547,7 +547,10 @@ namespace vk
|
|||
|
||||
//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)
|
||||
{
|
||||
region.protect(utils::protection::ro);
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
read_only_range = region.get_min_max(read_only_range);
|
||||
return ®ion;
|
||||
|
|
Loading…
Add table
Reference in a new issue