Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: Do not clobber CELL memory when a surface is partially inherited #12746

Merged
merged 6 commits into from Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -4326,7 +4326,7 @@ s64 spu_thread::get_ch_value(u32 ch)
atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64 attempts) -> bool
{
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
AUDIT(_this->id_type() == 1);
AUDIT(_this->id_type() == 2);

const auto old = +_this->state;

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Memory/vm.cpp
Expand Up @@ -1544,7 +1544,7 @@ namespace vm

static void load_memory_bytes(utils::serial& ar, u8* ptr, usz size)
{
AUDIT(ar.is_writing() && !(size % 128));
AUDIT(!ar.is_writing() && !(size % 128));

for (; size; ptr += 128 * 8, size -= 128 * 8)
{
Expand Down
31 changes: 31 additions & 0 deletions rpcs3/Emu/RSX/Common/simple_array.hpp
@@ -1,6 +1,7 @@
#pragma once

#include <util/types.hpp>
#include <functional>

namespace rsx
{
Expand Down Expand Up @@ -282,5 +283,35 @@ namespace rsx
{
return _data ? _data + _size : nullptr;
}

bool any(std::predicate<const Ty&> auto predicate) const
{
for (auto it = begin(); it != end(); ++it)
{
if (std::invoke(predicate, *it))
{
return true;
}
}
return false;
}

void filter(std::predicate<const Ty&> auto predicate)
{
if (!_size)
{
return;
}

for (auto ptr = _data, last = _data + _size - 1; ptr < last; ptr++)
{
if (!predicate(*ptr))
{
// Move item to the end of the list and shrink by 1
std::memcpy(ptr, last, sizeof(Ty));
last = _data + (--_size);
}
}
}
};
}
4 changes: 2 additions & 2 deletions rpcs3/Emu/RSX/Common/surface_store.h
Expand Up @@ -68,7 +68,7 @@ namespace rsx
std::pair<u32, surface_type> m_bound_depth_stencil = {};

// List of sections derived from a section that has been split and invalidated
std::vector<surface_type> orphaned_surfaces;
std::vector<std::pair<u32, surface_type>> orphaned_surfaces;

// List of sections that have been wholly inherited and invalidated
std::vector<surface_type> superseded_surfaces;
Expand Down Expand Up @@ -156,7 +156,7 @@ namespace rsx
}

ensure(region.target == Traits::get(sink));
orphaned_surfaces.push_back(region.target);
orphaned_surfaces.push_back({ address, region.target });
data.emplace(region.target->get_memory_range(), std::move(sink));
};

Expand Down
18 changes: 18 additions & 0 deletions rpcs3/Emu/RSX/Common/texture_cache.h
Expand Up @@ -3237,6 +3237,24 @@ namespace rsx
return m_predictor;
}

bool is_protected(u32 section_base_address, const address_range& test_range, rsx::texture_upload_context context)
{
reader_lock lock(m_cache_mutex);

const auto& block = m_storage.block_for(section_base_address);
for (const auto& tex : block)
{
if (tex.get_section_base() == section_base_address)
{
return tex.get_context() == context &&
tex.is_locked() &&
test_range.inside(tex.get_section_range());
}
}

return false;
}


/**
* The read only texture invalidate flag is set if a read only texture is trampled by framebuffer memory
Expand Down
87 changes: 48 additions & 39 deletions rpcs3/Emu/RSX/GL/GLRenderTargets.cpp
Expand Up @@ -310,54 +310,26 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
m_rtts.superseded_surfaces.clear();
}

const auto color_format = rsx::internals::surface_color_format_to_gl(m_framebuffer_layout.color_format);
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
{
if (!m_surface_info[i].address || !m_surface_info[i].pitch) continue;

const auto surface_range = m_surface_info[i].get_memory_range();
if (g_cfg.video.write_color_buffers)
{
// Mark buffer regions as NO_ACCESS on Cell-visible side
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_render_targets[i].second, surface_range, true,
m_surface_info[i].width, m_surface_info[i].height, m_surface_info[i].pitch,
color_format.format, color_format.type, color_format.swap_bytes);
}
else
{
m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface_range);
}
}

if (m_depth_surface_info.address && m_depth_surface_info.pitch)
{
const auto surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(m_framebuffer_layout.depth_format);
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch,
depth_format_gl.format, depth_format_gl.type, depth_format_gl.type != gl::texture::type::uint_24_8);
}
else
{
m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface_range);
}
}

if (!m_rtts.orphaned_surfaces.empty())
{
gl::texture::format format;
gl::texture::type type;
bool swap_bytes;

for (auto& surface : m_rtts.orphaned_surfaces)
for (auto& [base_addr, surface] : m_rtts.orphaned_surfaces)
{
const bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
!!g_cfg.video.write_color_buffers;

if (lock &&
!m_gl_texture_cache.is_protected(
base_addr,
surface->get_memory_range(),
rsx::texture_upload_context::framebuffer_storage))
{
lock = false;
}

if (!lock) [[likely]]
{
m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface->get_memory_range());
Expand Down Expand Up @@ -388,6 +360,43 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
m_rtts.orphaned_surfaces.clear();
}

const auto color_format = rsx::internals::surface_color_format_to_gl(m_framebuffer_layout.color_format);
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
{
if (!m_surface_info[i].address || !m_surface_info[i].pitch) continue;

const auto surface_range = m_surface_info[i].get_memory_range();
if (g_cfg.video.write_color_buffers)
{
// Mark buffer regions as NO_ACCESS on Cell-visible side
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_render_targets[i].second, surface_range, true,
m_surface_info[i].width, m_surface_info[i].height, m_surface_info[i].pitch,
color_format.format, color_format.type, color_format.swap_bytes);
}
else
{
m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface_range);
}
}

if (m_depth_surface_info.address && m_depth_surface_info.pitch)
{
const auto surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(m_framebuffer_layout.depth_format);
m_gl_texture_cache.lock_memory_region(
cmd, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_depth_surface_info.pitch,
depth_format_gl.format, depth_format_gl.type, depth_format_gl.type != gl::texture::type::uint_24_8);
}
else
{
m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface_range);
}
}

if (m_gl_texture_cache.get_ro_tex_invalidate_intr())
{
// Invalidate cached sampler state
Expand Down
83 changes: 46 additions & 37 deletions rpcs3/Emu/RSX/VK/VKGSRender.cpp
Expand Up @@ -2416,51 +2416,25 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_rtts.superseded_surfaces.clear();
}

const auto color_fmt_info = get_compatible_gcm_format(m_framebuffer_layout.color_format);
for (u8 index : m_draw_buffers)
{
if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue;

const utils::address_range surface_range = m_surface_info[index].get_memory_range();
if (g_cfg.video.write_color_buffers)
{
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_render_targets[index].second, surface_range, true,
m_surface_info[index].width, m_surface_info[index].height, m_framebuffer_layout.actual_color_pitch[index],
color_fmt_info.first, color_fmt_info.second);
}
else
{
m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface_range);
}
}

if (m_depth_surface_info.address && m_depth_surface_info.pitch)
{
const utils::address_range surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const u32 gcm_format = (m_depth_surface_info.depth_format == rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_framebuffer_layout.actual_zeta_pitch, gcm_format, true);
}
else
{
m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface_range);
}
}

if (!m_rtts.orphaned_surfaces.empty())
{
u32 gcm_format;
bool swap_bytes;

for (auto& surface : m_rtts.orphaned_surfaces)
for (auto& [base_addr, surface] : m_rtts.orphaned_surfaces)
{
const bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer :
!!g_cfg.video.write_color_buffers;

if (lock &&
!m_texture_cache.is_protected(
base_addr,
surface->get_memory_range(),
rsx::texture_upload_context::framebuffer_storage))
{
lock = false;
}

if (!lock) [[likely]]
{
m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface->get_memory_range());
Expand Down Expand Up @@ -2488,6 +2462,41 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_rtts.orphaned_surfaces.clear();
}

const auto color_fmt_info = get_compatible_gcm_format(m_framebuffer_layout.color_format);
for (u8 index : m_draw_buffers)
{
if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue;

const utils::address_range surface_range = m_surface_info[index].get_memory_range();
if (g_cfg.video.write_color_buffers)
{
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_render_targets[index].second, surface_range, true,
m_surface_info[index].width, m_surface_info[index].height, m_framebuffer_layout.actual_color_pitch[index],
color_fmt_info.first, color_fmt_info.second);
}
else
{
m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface_range);
}
}

if (m_depth_surface_info.address && m_depth_surface_info.pitch)
{
const utils::address_range surface_range = m_depth_surface_info.get_memory_range();
if (g_cfg.video.write_depth_buffer)
{
const u32 gcm_format = (m_depth_surface_info.depth_format == rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8;
m_texture_cache.lock_memory_region(
*m_current_command_buffer, m_rtts.m_bound_depth_stencil.second, surface_range, true,
m_depth_surface_info.width, m_depth_surface_info.height, m_framebuffer_layout.actual_zeta_pitch, gcm_format, true);
}
else
{
m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface_range);
}
}

m_current_renderpass_key = vk::get_renderpass_key(m_fbo_images);
m_cached_renderpass = vk::get_renderpass(*m_device, m_current_renderpass_key);

Expand Down