mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-16 23:40:24 +00:00
rsx: Implement memory tags for strict mode to validate render target memory
This commit is contained in:
parent
11bd65c2b5
commit
bf234dc668
5 changed files with 115 additions and 44 deletions
|
@ -186,6 +186,21 @@ namespace rsx
|
||||||
private:
|
private:
|
||||||
//Internal implementation methods and helpers
|
//Internal implementation methods and helpers
|
||||||
|
|
||||||
|
utils::protection get_memory_protection(u32 address)
|
||||||
|
{
|
||||||
|
auto found = m_cache.find(get_block_address(address));
|
||||||
|
if (found != m_cache.end())
|
||||||
|
{
|
||||||
|
for (const auto &tex : found->second.data)
|
||||||
|
{
|
||||||
|
if (tex.is_locked() && tex.overlaps(address, false))
|
||||||
|
return tex.get_protection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils::protection::rw;
|
||||||
|
}
|
||||||
|
|
||||||
//Get intersecting set - Returns all objects intersecting a given range and their owning blocks
|
//Get intersecting set - Returns all objects intersecting a given range and their owning blocks
|
||||||
std::vector<std::pair<section_storage_type*, ranged_storage*>> get_intersecting_set(u32 address, u32 range, bool check_whole_size)
|
std::vector<std::pair<section_storage_type*, ranged_storage*>> get_intersecting_set(u32 address, u32 range, bool check_whole_size)
|
||||||
{
|
{
|
||||||
|
@ -723,50 +738,56 @@ namespace rsx
|
||||||
//TODO: When framebuffer Y compression is properly handled, this section can be removed. A more accurate framebuffer storage check exists below this block
|
//TODO: When framebuffer Y compression is properly handled, this section can be removed. A more accurate framebuffer storage check exists below this block
|
||||||
if (auto texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
|
if (auto texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
|
||||||
{
|
{
|
||||||
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
if (test_framebuffer(texaddr))
|
||||||
LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension);
|
|
||||||
|
|
||||||
for (const auto& tex : m_rtts.m_bound_render_targets)
|
|
||||||
{
|
{
|
||||||
if (std::get<0>(tex) == texaddr)
|
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
||||||
|
LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension);
|
||||||
|
|
||||||
|
for (const auto& tex : m_rtts.m_bound_render_targets)
|
||||||
|
{
|
||||||
|
if (std::get<0>(tex) == texaddr)
|
||||||
|
{
|
||||||
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
|
{
|
||||||
|
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
|
||||||
|
return create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//issue a texture barrier to ensure previous writes are visible
|
||||||
|
insert_texture_barrier();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return texptr->get_view();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
|
||||||
|
{
|
||||||
|
if (test_framebuffer(texaddr))
|
||||||
|
{
|
||||||
|
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
||||||
|
LOG_ERROR(RSX, "Texture resides in depth buffer memory, but requested type is not 2D (%d)", (u32)extended_dimension);
|
||||||
|
|
||||||
|
if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
|
||||||
{
|
{
|
||||||
if (g_cfg.video.strict_rendering_mode)
|
if (g_cfg.video.strict_rendering_mode)
|
||||||
{
|
{
|
||||||
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
|
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
|
||||||
return create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height());
|
return create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//issue a texture barrier to ensure previous writes are visible
|
//issue a texture barrier to ensure previous writes are visible
|
||||||
insert_texture_barrier();
|
insert_texture_barrier();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return texptr->get_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
return texptr->get_view();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
|
|
||||||
{
|
|
||||||
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
|
||||||
LOG_ERROR(RSX, "Texture resides in depth buffer memory, but requested type is not 2D (%d)", (u32)extended_dimension);
|
|
||||||
|
|
||||||
if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
|
|
||||||
{
|
|
||||||
if (g_cfg.video.strict_rendering_mode)
|
|
||||||
{
|
|
||||||
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
|
|
||||||
return create_temporary_subresource_view(cmd, texptr, format, 0, 0, texptr->width(), texptr->height());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//issue a texture barrier to ensure previous writes are visible
|
|
||||||
insert_texture_barrier();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return texptr->get_view();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +831,7 @@ namespace rsx
|
||||||
const u32 internal_width = (const u32)(tex_width * internal_scale);
|
const u32 internal_width = (const u32)(tex_width * internal_scale);
|
||||||
|
|
||||||
const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, internal_width, tex_height, tex_pitch, true);
|
const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, internal_width, tex_height, tex_pitch, true);
|
||||||
if (rsc.surface)
|
if (rsc.surface && test_framebuffer(texaddr))
|
||||||
{
|
{
|
||||||
//TODO: Check that this region is not cpu-dirty before doing a copy
|
//TODO: Check that this region is not cpu-dirty before doing a copy
|
||||||
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
if (extended_dimension != rsx::texture_dimension_extended::texture_dimension_2d)
|
||||||
|
@ -1248,5 +1269,36 @@ namespace rsx
|
||||||
{
|
{
|
||||||
return m_texture_memory_in_use;
|
return m_texture_memory_in_use;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tag_framebuffer(u32 texaddr)
|
||||||
|
{
|
||||||
|
if (!g_cfg.video.strict_rendering_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (get_memory_protection(texaddr))
|
||||||
|
{
|
||||||
|
case utils::protection::no:
|
||||||
|
return;
|
||||||
|
case utils::protection::ro:
|
||||||
|
LOG_ERROR(RSX, "Framebuffer memory occupied by regular texture!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::ps3::write32(texaddr, texaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_framebuffer(u32 texaddr)
|
||||||
|
{
|
||||||
|
if (!g_cfg.video.strict_rendering_mode)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer)
|
||||||
|
{
|
||||||
|
if (get_memory_protection(texaddr) == utils::protection::no)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm::ps3::read32(texaddr) == texaddr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -947,15 +947,17 @@ bool GLGSRender::check_program_state()
|
||||||
if (!is_depth)
|
if (!is_depth)
|
||||||
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
|
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
|
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
|
||||||
|
|
||||||
if (!surface && m_gl_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
|
const bool dirty_framebuffer = (surface != nullptr && !m_gl_texture_cache.test_framebuffer(texaddr));
|
||||||
return std::make_tuple(true, 0);
|
if (dirty_framebuffer || !surface)
|
||||||
}
|
|
||||||
|
|
||||||
if (!surface)
|
|
||||||
{
|
{
|
||||||
|
if (is_depth && m_gl_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
|
||||||
|
return std::make_tuple(true, 0);
|
||||||
|
|
||||||
|
if (dirty_framebuffer)
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
|
||||||
auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, 0, 0, tex.pitch());
|
auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, 0, 0, tex.pitch());
|
||||||
if (!rsc.surface || rsc.is_depth_surface != is_depth)
|
if (!rsc.surface || rsc.is_depth_surface != is_depth)
|
||||||
return std::make_tuple(false, 0);
|
return std::make_tuple(false, 0);
|
||||||
|
|
|
@ -236,6 +236,8 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||||
surface_info[i].pitch = 0;
|
surface_info[i].pitch = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_gl_texture_cache.tag_framebuffer(surface_addresses[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
surface_info[i] = {};
|
surface_info[i] = {};
|
||||||
|
@ -266,6 +268,8 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||||
depth_surface_info.pitch = 0;
|
depth_surface_info.pitch = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_gl_texture_cache.tag_framebuffer(depth_address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
depth_surface_info = {};
|
depth_surface_info = {};
|
||||||
|
|
|
@ -1819,14 +1819,23 @@ bool VKGSRender::check_program_status()
|
||||||
if (!is_depth)
|
if (!is_depth)
|
||||||
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
|
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
|
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
|
||||||
|
|
||||||
if (!surface && m_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
|
const bool dirty_framebuffer = (surface != nullptr && !m_texture_cache.test_framebuffer(texaddr));
|
||||||
|
if (dirty_framebuffer || !surface)
|
||||||
|
{
|
||||||
|
if (is_depth && m_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
|
||||||
return std::make_tuple(true, 0);
|
return std::make_tuple(true, 0);
|
||||||
}
|
|
||||||
|
|
||||||
if (!surface) return std::make_tuple(false, 0);
|
if (dirty_framebuffer)
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
|
||||||
|
auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, 0, 0, tex.pitch());
|
||||||
|
if (!rsc.surface || rsc.is_depth_surface != is_depth)
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
|
||||||
|
surface = rsc.surface;
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_tuple(true, surface->native_pitch);
|
return std::make_tuple(true, surface->native_pitch);
|
||||||
};
|
};
|
||||||
|
@ -2284,6 +2293,8 @@ void VKGSRender::prepare_rtts()
|
||||||
//Ignore this buffer (usually set to 64)
|
//Ignore this buffer (usually set to 64)
|
||||||
m_surface_info[index].pitch = 0;
|
m_surface_info[index].pitch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_texture_cache.tag_framebuffer(surface_addresses[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::get<0>(m_rtts.m_bound_depth_stencil) != 0)
|
if (std::get<0>(m_rtts.m_bound_depth_stencil) != 0)
|
||||||
|
@ -2297,6 +2308,8 @@ void VKGSRender::prepare_rtts()
|
||||||
|
|
||||||
if (m_depth_surface_info.pitch <= 64 && clip_width > m_depth_surface_info.pitch)
|
if (m_depth_surface_info.pitch <= 64 && clip_width > m_depth_surface_info.pitch)
|
||||||
m_depth_surface_info.pitch = 0;
|
m_depth_surface_info.pitch = 0;
|
||||||
|
|
||||||
|
m_texture_cache.tag_framebuffer(zeta_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_draw_buffers_count = static_cast<u32>(draw_buffers.size());
|
m_draw_buffers_count = static_cast<u32>(draw_buffers.size());
|
||||||
|
|
|
@ -239,7 +239,7 @@ namespace rsx
|
||||||
return std::make_pair(min, max);
|
return std::make_pair(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::protection get_protection()
|
utils::protection get_protection() const
|
||||||
{
|
{
|
||||||
return protection;
|
return protection;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue