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; rsx::address_range m_depth_stencil_memory_range;
bool m_invalidate_on_write = false; 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; 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; return;
} }
write_tag = cache_tag; // TODO: Take WCB/WDB into account. Should speed this up a bit by skipping sync_tag calls
m_skip_write_updates = false; write_tag = rsx::get_shared_tag();
int tagged = 0;
// Tag surfaces for (u8 i = m_bound_render_targets_config.first, count = 0;
if (color) count < m_bound_render_targets_config.second;
++count, ++i)
{ {
for (int i = m_bound_render_targets_config.first, count = 0; if (auto surface = m_bound_render_targets[i].second;
count < m_bound_render_targets_config.second; surface && color_mrt_writes_enabled[i])
++i, ++count)
{ {
if (!color[i]) surface->on_write(write_tag);
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;
} }
} }
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; zsurface->on_write(write_tag);
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;
} }
} }

View File

@ -178,7 +178,7 @@ namespace rsx
virtual bool is_depth_surface() const = 0; virtual bool is_depth_surface() const = 0;
virtual void release_ref(image_storage_type) 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) 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) switch (metrics)
{ {
@ -207,22 +207,22 @@ namespace rsx
} }
} }
virtual u32 get_rsx_pitch() const inline u32 get_rsx_pitch() const
{ {
return rsx_pitch; return rsx_pitch;
} }
virtual u32 get_native_pitch() const inline u32 get_native_pitch() const
{ {
return native_pitch; return native_pitch;
} }
u8 get_bpp() const inline u8 get_bpp() const
{ {
return u8(get_native_pitch() / get_surface_width(rsx::surface_metrics::samples)); return u8(get_native_pitch() / get_surface_width(rsx::surface_metrics::samples));
} }
u8 get_spp() const inline u8 get_spp() const
{ {
return spp; return spp;
} }
@ -278,17 +278,17 @@ namespace rsx
format_info.gcm_depth_format = format; 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; 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; return format_info.gcm_depth_format;
} }
u32 get_gcm_format() const inline u32 get_gcm_format() const
{ {
return 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(); 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(); 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> 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) std::pair<bool, surface_type> is_expired(surface_store_type& surface_cache)
{ {
if (upload_context != rsx::texture_upload_context::framebuffer_storage || if (upload_context != rsx::texture_upload_context::framebuffer_storage)
surface_cache_tag == surface_cache.cache_tag)
{ {
return { false, nullptr }; return {};
} }
// Expired, but may still be valid. Check if the texture is still accessible // 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; 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); if (!(surface = surface_cache.get_surface_at(ref_address)))
surface && surface == surface_cache.get_surface_at(ref_address))
{ {
// Fast sync // Compositing op. Just ignore expiry for now
surface_cache_tag = surface_cache.cache_tag; ensure(!ref_image);
is_cyclic_reference = surface_cache.address_is_bound(ref_address); 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 }; return { false, surface };
} }
} }
// Reupload
return { true, nullptr }; return { true, nullptr };
} }
}; };
@ -2155,7 +2182,7 @@ namespace rsx
} }
result.ref_address = attributes.address; 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) if (subsurface_count == 1)
{ {

View File

@ -677,7 +677,7 @@ void GLGSRender::end()
} }
while (rsx::method_registers.current_draw_clause.next()); 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_attrib_ring_buffer->notify();
m_index_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) if (update_color || update_z)
{ {
const bool write_all_mask[] = { true, true, true, true }; m_rtts.on_write({ update_color, update_color, update_color, update_color }, update_z);
m_rtts.on_write(update_color ? write_all_mask : nullptr, update_z);
} }
glClear(mask); glClear(mask);

View File

@ -1116,7 +1116,7 @@ void VKGSRender::end()
m_current_command_buffer->flags &= ~(vk::command_buffer::cb_has_conditional_render); 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(); rsx::thread::end();
} }

View File

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

View File

@ -772,6 +772,12 @@ namespace vk
return this; 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! // A read barrier should have been called before this!
ensure(resolve_surface); // "Read access without explicit barrier" ensure(resolve_surface); // "Read access without explicit barrier"
ensure(!(msaa_flags & rsx::surface_state_flags::require_resolve)); 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 if (!write_barrier_sync_tag) write_barrier_sync_tag++; // Activate barrier sync
cyclic_reference_sync_tag = write_barrier_sync_tag; // Match tags 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() void render_target::reset_surface_counters()