mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
rsx: Fix surface write coherency when MSAA is active
This commit is contained in:
parent
cd97d74f0f
commit
6812fa4764
8 changed files with 78 additions and 73 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue