rsx: Avoid expensive protection scan by sharing some data between surface and texture cache

This commit is contained in:
kd-11 2022-12-15 15:39:55 +03:00 committed by kd-11
parent 8ec01450f8
commit a05e3f02b8
9 changed files with 80 additions and 45 deletions

View File

@ -125,7 +125,7 @@ namespace rsx
};
template <typename image_storage_type>
struct render_target_descriptor
struct render_target_descriptor : public rsx::ref_counted
{
u64 last_use_tag = 0; // tag indicating when this block was last confirmed to have been written to
u32 base_addr = 0;
@ -165,6 +165,13 @@ namespace rsx
}
format_info;
struct
{
u64 timestamp = 0;
bool locked = false;
}
texture_cache_metadata;
render_target_descriptor() {}
virtual ~render_target_descriptor()
@ -178,7 +185,11 @@ namespace rsx
virtual image_storage_type get_surface(rsx::surface_access access_type) = 0;
virtual bool is_depth_surface() const = 0;
virtual void release_ref(image_storage_type) const = 0;
void reset()
{
texture_cache_metadata = {};
}
template<rsx::surface_metrics Metrics = rsx::surface_metrics::pixels, typename T = u32>
T get_surface_width() const
@ -438,7 +449,7 @@ namespace rsx
{
for (auto &e : old_contents)
{
release_ref(e.source);
ensure(dynamic_cast<rsx::ref_counted*>(e.source))->release();
}
old_contents.clear();
@ -696,5 +707,31 @@ namespace rsx
ensure(access_type.is_read() || access_type.is_transfer());
transform_samples_to_pixels(region);
}
void on_lock()
{
add_ref();
texture_cache_metadata.locked = true;
texture_cache_metadata.timestamp = rsx::get_shared_tag();
}
void on_unlock()
{
texture_cache_metadata.locked = false;
texture_cache_metadata.timestamp = rsx::get_shared_tag();
release();
}
bool is_locked() const
{
return texture_cache_metadata.locked;
}
bool has_flushable_data() const
{
ensure(is_locked());
ensure(texture_cache_metadata.timestamp);
return (texture_cache_metadata.timestamp < last_use_tag);
}
};
}

View File

@ -1324,6 +1324,26 @@ namespace rsx
return (get_protection() == utils::protection::no);
}
bool is_synchronized() const
{
return synchronized;
}
bool is_flushed() const
{
return flushed;
}
bool should_flush() const
{
if (context == rsx::texture_upload_context::framebuffer_storage)
{
const auto surface = derived()->get_render_target();
return surface->has_flushable_data();
}
return true;
}
private:
/**
@ -1359,14 +1379,14 @@ namespace rsx
{
// Locked memory. We have to take ownership of the object in the surface cache as well
auto surface = derived()->get_render_target();
surface->add_ref();
surface->on_lock();
}
else if (old_prot == utils::protection::no && prot != utils::protection::no)
{
// Release the surface, the cache can remove it if needed
ensure(prot == utils::protection::rw);
auto surface = derived()->get_render_target();
surface->release();
surface->on_unlock();
}
}
}

View File

@ -322,10 +322,15 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
!!g_cfg.video.write_color_buffers;
if (lock &&
#ifdef TEXTURE_CACHE_DEBUG
!m_gl_texture_cache.is_protected(
base_addr,
surface->get_memory_range(),
rsx::texture_upload_context::framebuffer_storage))
rsx::texture_upload_context::framebuffer_storage)
#else
!surface->is_locked()
#endif
)
{
lock = false;
}

View File

@ -47,7 +47,7 @@ namespace rsx
namespace gl
{
class render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<texture*>
class render_target : public viewable_image, public rsx::render_target_descriptor<texture*>
{
void clear_memory(gl::command_context& cmd);
void load_memory(gl::command_context& cmd);
@ -81,11 +81,6 @@ namespace gl
return !!(aspect() & gl::image_aspect::depth);
}
void release_ref(texture* t) const override
{
static_cast<gl::render_target*>(t)->release();
}
viewable_image* get_surface(rsx::surface_access /*access_type*/) override
{
// TODO
@ -232,6 +227,7 @@ struct gl_render_target_traits
sink->set_rsx_pitch(ref->get_rsx_pitch());
sink->set_old_contents_region(prev, false);
sink->texture_cache_metadata = ref->texture_cache_metadata;
sink->last_use_tag = ref->last_use_tag;
sink->raster_type = ref->raster_type; // Can't actually cut up swizzled data
}
@ -293,6 +289,7 @@ struct gl_render_target_traits
}
surface->release();
surface->reset();
}
static

View File

@ -383,26 +383,6 @@ namespace gl
return format;
}
bool is_flushed() const
{
return flushed;
}
bool is_synchronized() const
{
return synchronized;
}
void set_flushed(bool state)
{
flushed = state;
}
bool is_empty() const
{
return vram_texture == nullptr;
}
gl::texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
{
return vram_texture->get_view(remap_encoding, remap);

View File

@ -2450,10 +2450,15 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
!!g_cfg.video.write_color_buffers;
if (lock &&
#ifdef TEXTURE_CACHE_DEBUG
!m_texture_cache.is_protected(
base_addr,
surface->get_memory_range(),
rsx::texture_upload_context::framebuffer_storage))
rsx::texture_upload_context::framebuffer_storage)
#else
!surface->is_locked()
#endif
)
{
lock = false;
}

View File

@ -788,11 +788,6 @@ namespace vk
return !!(aspect() & VK_IMAGE_ASPECT_DEPTH_BIT);
}
void render_target::release_ref(vk::viewable_image* t) const
{
static_cast<vk::render_target*>(t)->release();
}
bool render_target::matches_dimensions(u16 _width, u16 _height) const
{
// Use forward scaling to account for rounding and clamping errors

View File

@ -24,7 +24,7 @@ namespace vk
void resolve_image(vk::command_buffer& cmd, vk::viewable_image* dst, vk::viewable_image* src);
void unresolve_image(vk::command_buffer& cmd, vk::viewable_image* dst, vk::viewable_image* src);
class render_target : public viewable_image, public rsx::ref_counted, public rsx::render_target_descriptor<vk::viewable_image*>
class render_target : public viewable_image, public rsx::render_target_descriptor<vk::viewable_image*>
{
u64 cyclic_reference_sync_tag = 0;
u64 write_barrier_sync_tag = 0;
@ -64,7 +64,6 @@ namespace vk
vk::viewable_image* get_surface(rsx::surface_access access_type) override;
bool is_depth_surface() const override;
void release_ref(vk::viewable_image* t) const override;
bool matches_dimensions(u16 _width, u16 _height) const;
void reset_surface_counters();
@ -338,6 +337,7 @@ namespace vk
sink->rsx_pitch = ref->get_rsx_pitch();
sink->set_old_contents_region(prev, false);
sink->texture_cache_metadata = ref->texture_cache_metadata;
sink->last_use_tag = ref->last_use_tag;
sink->raster_type = ref->raster_type; // Can't actually cut up swizzled data
}
@ -411,6 +411,7 @@ namespace vk
}
surface->release();
surface->reset();
}
static void notify_surface_persist(const std::unique_ptr<vk::render_target>& /*surface*/)

View File

@ -345,11 +345,6 @@ namespace vk
}
}
bool is_synchronized() const
{
return synchronized;
}
bool has_compatible_format(vk::image* tex) const
{
return vram_texture->info.format == tex->info.format;