rsx: Fix surface write coherency when MSAA is active

This commit is contained in:
kd-11 2022-03-05 16:19:17 +03:00 committed by kd-11
parent cd97d74f0f
commit 6812fa4764
8 changed files with 78 additions and 73 deletions

View File

@ -52,7 +52,6 @@ namespace rsx
rsx::address_range m_depth_stencil_memory_range;
bool m_invalidate_on_write = false;
bool m_skip_write_updates = false;
rsx::surface_raster_type m_active_raster_type = rsx::surface_raster_type::linear;
@ -1118,62 +1117,31 @@ namespace rsx
}
}
void on_write(const bool* color, bool z)
void on_write(const std::array<bool, 4>& color_mrt_writes_enabled, const bool depth_stencil_writes_enabled)
{
if (write_tag == cache_tag && m_skip_write_updates)
if (write_tag >= cache_tag && !m_invalidate_on_write)
{
// Nothing to do
ensure(!m_invalidate_on_write);
return;
}
write_tag = cache_tag;
m_skip_write_updates = false;
int tagged = 0;
// TODO: Take WCB/WDB into account. Should speed this up a bit by skipping sync_tag calls
write_tag = rsx::get_shared_tag();
// Tag surfaces
if (color)
for (u8 i = m_bound_render_targets_config.first, count = 0;
count < m_bound_render_targets_config.second;
++count, ++i)
{
for (int i = m_bound_render_targets_config.first, count = 0;
count < m_bound_render_targets_config.second;
++i, ++count)
if (auto surface = m_bound_render_targets[i].second;
surface && color_mrt_writes_enabled[i])
{
if (!color[i])
continue;
auto& surface = m_bound_render_targets[i].second;
if (surface->last_use_tag != write_tag)
{
m_bound_render_targets[i].second->on_write(write_tag, surface_state_flags::require_resolve, m_active_raster_type);
}
else if (m_invalidate_on_write)
{
m_bound_render_targets[i].second->on_invalidate_children();
}
++tagged;
surface->on_write(write_tag);
}
}
if (z && m_bound_depth_stencil.first)
if (auto zsurface = m_bound_depth_stencil.second;
zsurface && depth_stencil_writes_enabled)
{
auto& surface = m_bound_depth_stencil.second;
if (surface->last_use_tag != write_tag)
{
m_bound_depth_stencil.second->on_write(write_tag, surface_state_flags::require_resolve, m_active_raster_type);
}
else if (m_invalidate_on_write)
{
m_bound_depth_stencil.second->on_invalidate_children();
}
++tagged;
}
if (!m_invalidate_on_write && tagged == m_bound_buffers_count)
{
// Skip any further updates as all active surfaces have been updated
m_skip_write_updates = true;
zsurface->on_write(write_tag);
}
}

View File

@ -178,7 +178,7 @@ namespace rsx
virtual bool is_depth_surface() const = 0;
virtual void release_ref(image_storage_type) const = 0;
virtual u32 get_surface_width(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const
inline u32 get_surface_width(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const
{
switch (metrics)
{
@ -193,7 +193,7 @@ namespace rsx
}
}
virtual u32 get_surface_height(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const
inline u32 get_surface_height(rsx::surface_metrics metrics = rsx::surface_metrics::pixels) const
{
switch (metrics)
{
@ -207,22 +207,22 @@ namespace rsx
}
}
virtual u32 get_rsx_pitch() const
inline u32 get_rsx_pitch() const
{
return rsx_pitch;
}
virtual u32 get_native_pitch() const
inline u32 get_native_pitch() const
{
return native_pitch;
}
u8 get_bpp() const
inline u8 get_bpp() const
{
return u8(get_native_pitch() / get_surface_width(rsx::surface_metrics::samples));
}
u8 get_spp() const
inline u8 get_spp() const
{
return spp;
}
@ -278,17 +278,17 @@ namespace rsx
format_info.gcm_depth_format = format;
}
rsx::surface_color_format get_surface_color_format() const
inline rsx::surface_color_format get_surface_color_format() const
{
return format_info.gcm_color_format;
}
rsx::surface_depth_format2 get_surface_depth_format() const
inline rsx::surface_depth_format2 get_surface_depth_format() const
{
return format_info.gcm_depth_format;
}
u32 get_gcm_format() const
inline u32 get_gcm_format() const
{
return
(
@ -298,12 +298,12 @@ namespace rsx
);
}
bool dirty() const
inline bool dirty() const
{
return (state_flags != rsx::surface_state_flags::ready) || !old_contents.empty();
}
bool write_through() const
inline bool write_through() const
{
return (state_flags & rsx::surface_state_flags::erase_bkgnd) && old_contents.empty();
}

View File

@ -285,26 +285,53 @@ namespace rsx
template <typename surface_store_type, typename surface_type = typename surface_store_type::surface_type>
std::pair<bool, surface_type> is_expired(surface_store_type& surface_cache)
{
if (upload_context != rsx::texture_upload_context::framebuffer_storage ||
surface_cache_tag == surface_cache.cache_tag)
if (upload_context != rsx::texture_upload_context::framebuffer_storage)
{
return { false, nullptr };
return {};
}
// Expired, but may still be valid. Check if the texture is still accessible
auto ref_image = image_handle ? image_handle->image() : external_subresource_desc.external_handle;
if (ref_image)
surface_type surface = dynamic_cast<surface_type>(ref_image);
// Try and grab a cache reference in case of MSAA resolve target or compositing op
if (!surface)
{
if (auto surface = dynamic_cast<surface_type>(ref_image);
surface && surface == surface_cache.get_surface_at(ref_address))
if (!(surface = surface_cache.get_surface_at(ref_address)))
{
// Fast sync
surface_cache_tag = surface_cache.cache_tag;
is_cyclic_reference = surface_cache.address_is_bound(ref_address);
// Compositing op. Just ignore expiry for now
ensure(!ref_image);
return {};
}
}
ensure(surface);
if (!ref_image || surface->get_surface(rsx::surface_access::gpu_reference) == ref_image)
{
// Same image, so configuration did not change.
if (surface->last_use_tag <= surface_cache_tag)
{
external_subresource_desc.do_not_cache = false;
return {};
}
// Image was written to since last bind. Insert texture barrier.
surface_cache_tag = surface->last_use_tag;
is_cyclic_reference = surface_cache.address_is_bound(ref_address);
external_subresource_desc.do_not_cache = is_cyclic_reference;
switch (external_subresource_desc.op)
{
case deferred_request_command::copy_image_dynamic:
case deferred_request_command::copy_image_static:
external_subresource_desc.op = (is_cyclic_reference) ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static;
[[ fallthrough ]];
default:
return { false, surface };
}
}
// Reupload
return { true, nullptr };
}
};
@ -2155,7 +2182,7 @@ namespace rsx
}
result.ref_address = attributes.address;
result.surface_cache_tag = m_rtts.cache_tag;
result.surface_cache_tag = m_rtts.write_tag;
if (subsurface_count == 1)
{

View File

@ -677,7 +677,7 @@ void GLGSRender::end()
}
while (rsx::method_registers.current_draw_clause.next());
m_rtts.on_write(m_framebuffer_layout.color_write_enabled.data(), m_framebuffer_layout.zeta_write_enabled);
m_rtts.on_write(m_framebuffer_layout.color_write_enabled, m_framebuffer_layout.zeta_write_enabled);
m_attrib_ring_buffer->notify();
m_index_ring_buffer->notify();

View File

@ -662,8 +662,7 @@ void GLGSRender::clear_surface(u32 arg)
if (update_color || update_z)
{
const bool write_all_mask[] = { true, true, true, true };
m_rtts.on_write(update_color ? write_all_mask : nullptr, update_z);
m_rtts.on_write({ update_color, update_color, update_color, update_color }, update_z);
}
glClear(mask);

View File

@ -1116,7 +1116,7 @@ void VKGSRender::end()
m_current_command_buffer->flags &= ~(vk::command_buffer::cb_has_conditional_render);
}
m_rtts.on_write(m_framebuffer_layout.color_write_enabled.data(), m_framebuffer_layout.zeta_write_enabled);
m_rtts.on_write(m_framebuffer_layout.color_write_enabled, m_framebuffer_layout.zeta_write_enabled);
rsx::thread::end();
}

View File

@ -1449,8 +1449,7 @@ void VKGSRender::clear_surface(u32 mask)
if (update_color || update_z)
{
const bool write_all_mask[] = { true, true, true, true };
m_rtts.on_write(update_color ? write_all_mask : nullptr, update_z);
m_rtts.on_write({ update_color, update_color, update_color, update_color }, update_z);
}
if (!clear_descriptors.empty())

View File

@ -772,6 +772,12 @@ namespace vk
return this;
}
if (access_type == rsx::surface_access::gpu_reference)
{
// WARNING: Can return MSAA data result if no read barrier was issued
return resolve_surface ? resolve_surface.get() : this;
}
// A read barrier should have been called before this!
ensure(resolve_surface); // "Read access without explicit barrier"
ensure(!(msaa_flags & rsx::surface_state_flags::require_resolve));
@ -801,9 +807,15 @@ namespace vk
{
if (!write_barrier_sync_tag) write_barrier_sync_tag++; // Activate barrier sync
cyclic_reference_sync_tag = write_barrier_sync_tag; // Match tags
vk::insert_texture_barrier(cmd, this, VK_IMAGE_LAYOUT_GENERAL);
return;
}
vk::insert_texture_barrier(cmd, this, VK_IMAGE_LAYOUT_GENERAL);
if (msaa_flags & rsx::surface_state_flags::require_resolve)
{
resolve(cmd);
}
}
void render_target::reset_surface_counters()