mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-03-01 11:07:31 +01:00
rsx: Refactor create_subresource_view(deferred_subresource&) and implement a subresource cache
- This limits the number of times an image is copied and improves performance
This commit is contained in:
parent
1fa18757fc
commit
60c7a508a7
|
|
@ -132,8 +132,78 @@ namespace rsx
|
|||
{ CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP }
|
||||
};
|
||||
|
||||
protected:
|
||||
public:
|
||||
//Struct to hold data on sections to be paged back onto cpu memory
|
||||
struct thrashed_set
|
||||
{
|
||||
bool violation_handled = false;
|
||||
std::vector<section_storage_type*> affected_sections; //Always laid out with flushable sections first then other affected sections last
|
||||
int num_flushable = 0;
|
||||
u64 cache_tag = 0;
|
||||
u32 address_base = 0;
|
||||
u32 address_range = 0;
|
||||
};
|
||||
|
||||
struct deferred_subresource
|
||||
{
|
||||
image_resource_type external_handle = 0;
|
||||
std::array<image_resource_type, 6> external_cubemap_sources;
|
||||
u32 base_address = 0;
|
||||
u32 gcm_format = 0;
|
||||
u16 x = 0;
|
||||
u16 y = 0;
|
||||
u16 width = 0;
|
||||
u16 height = 0;
|
||||
bool is_cubemap = false;
|
||||
|
||||
deferred_subresource()
|
||||
{}
|
||||
|
||||
deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h) :
|
||||
external_handle(_res), base_address(_addr), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h)
|
||||
{}
|
||||
};
|
||||
|
||||
struct sampled_image_descriptor : public sampled_image_descriptor_base
|
||||
{
|
||||
image_view_type image_handle = 0;
|
||||
deferred_subresource external_subresource_desc = {};
|
||||
bool flag = false;
|
||||
|
||||
sampled_image_descriptor()
|
||||
{}
|
||||
|
||||
sampled_image_descriptor(image_view_type handle, const texture_upload_context ctx, const bool is_depth, const f32 x_scale, const f32 y_scale, const rsx::texture_dimension_extended type)
|
||||
{
|
||||
image_handle = handle;
|
||||
upload_context = ctx;
|
||||
is_depth_texture = is_depth;
|
||||
scale_x = x_scale;
|
||||
scale_y = y_scale;
|
||||
image_type = type;
|
||||
}
|
||||
|
||||
sampled_image_descriptor(image_resource_type external_handle, u32 base_address, u32 gcm_format, u16 x_offset, u16 y_offset, u16 width, u16 height,
|
||||
const texture_upload_context ctx, const bool is_depth, const f32 x_scale, const f32 y_scale, const rsx::texture_dimension_extended type)
|
||||
{
|
||||
external_subresource_desc = { external_handle, base_address, gcm_format, x_offset, y_offset, width, height };
|
||||
|
||||
image_handle = 0;
|
||||
upload_context = ctx;
|
||||
is_depth_texture = is_depth;
|
||||
scale_x = x_scale;
|
||||
scale_y = y_scale;
|
||||
image_type = type;
|
||||
}
|
||||
|
||||
void set_external_cubemap_resources(std::array<image_resource_type, 6> images)
|
||||
{
|
||||
external_subresource_desc.external_cubemap_sources = images;
|
||||
external_subresource_desc.is_cubemap = true;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
struct ranged_storage
|
||||
{
|
||||
std::vector<section_storage_type> data; //Stored data
|
||||
|
|
@ -178,6 +248,7 @@ namespace rsx
|
|||
|
||||
shared_mutex m_cache_mutex;
|
||||
std::unordered_map<u32, ranged_storage> m_cache;
|
||||
std::unordered_multimap<u32, std::pair<deferred_subresource, image_view_type>> m_temporary_subresource_cache;
|
||||
|
||||
std::atomic<u64> m_cache_update_tag = {};
|
||||
|
||||
|
|
@ -214,76 +285,6 @@ namespace rsx
|
|||
m_cache_update_tag = get_system_time();
|
||||
}
|
||||
|
||||
public:
|
||||
//Struct to hold data on sections to be paged back onto cpu memory
|
||||
struct thrashed_set
|
||||
{
|
||||
bool violation_handled = false;
|
||||
std::vector<section_storage_type*> affected_sections; //Always laid out with flushable sections first then other affected sections last
|
||||
int num_flushable = 0;
|
||||
u64 cache_tag = 0;
|
||||
u32 address_base = 0;
|
||||
u32 address_range = 0;
|
||||
};
|
||||
|
||||
struct deferred_subresource
|
||||
{
|
||||
image_resource_type external_handle = 0;
|
||||
std::array<image_resource_type, 6> external_cubemap_sources;
|
||||
u32 gcm_format = 0;
|
||||
u16 x = 0;
|
||||
u16 y = 0;
|
||||
u16 width = 0;
|
||||
u16 height = 0;
|
||||
bool is_cubemap = false;
|
||||
|
||||
deferred_subresource()
|
||||
{}
|
||||
|
||||
deferred_subresource(image_resource_type _res, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h):
|
||||
external_handle(_res), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h)
|
||||
{}
|
||||
};
|
||||
|
||||
struct sampled_image_descriptor : public sampled_image_descriptor_base
|
||||
{
|
||||
image_view_type image_handle = 0;
|
||||
deferred_subresource external_subresource_desc = {};
|
||||
bool flag = false;
|
||||
|
||||
sampled_image_descriptor()
|
||||
{}
|
||||
|
||||
sampled_image_descriptor(image_view_type handle, const texture_upload_context ctx, const bool is_depth, const f32 x_scale, const f32 y_scale, const rsx::texture_dimension_extended type)
|
||||
{
|
||||
image_handle = handle;
|
||||
upload_context = ctx;
|
||||
is_depth_texture = is_depth;
|
||||
scale_x = x_scale;
|
||||
scale_y = y_scale;
|
||||
image_type = type;
|
||||
}
|
||||
|
||||
sampled_image_descriptor(image_resource_type external_handle, u32 gcm_format, u16 x_offset, u16 y_offset, u16 width, u16 height,
|
||||
const texture_upload_context ctx, const bool is_depth, const f32 x_scale, const f32 y_scale, const rsx::texture_dimension_extended type)
|
||||
{
|
||||
external_subresource_desc = {external_handle, gcm_format, x_offset, y_offset, width, height};
|
||||
|
||||
image_handle = 0;
|
||||
upload_context = ctx;
|
||||
is_depth_texture = is_depth;
|
||||
scale_x = x_scale;
|
||||
scale_y = y_scale;
|
||||
image_type = type;
|
||||
}
|
||||
|
||||
void set_external_cubemap_resources(std::array<image_resource_type, 6> images)
|
||||
{
|
||||
external_subresource_desc.external_cubemap_sources = images;
|
||||
external_subresource_desc.is_cubemap = true;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
//Internal implementation methods and helpers
|
||||
|
||||
|
|
@ -994,6 +995,40 @@ namespace rsx
|
|||
m_unreleased_texture_objects = 0;
|
||||
}
|
||||
|
||||
image_view_type create_temporary_subresource(commandbuffer_type &cmd, deferred_subresource& desc)
|
||||
{
|
||||
const auto found = m_temporary_subresource_cache.equal_range(desc.base_address);
|
||||
for (auto It = found.first; It != found.second; ++It)
|
||||
{
|
||||
const auto& found_desc = It->second.first;
|
||||
if (found_desc.external_handle != desc.external_handle ||
|
||||
found_desc.is_cubemap != desc.is_cubemap ||
|
||||
found_desc.x != desc.x || found_desc.y != desc.y ||
|
||||
found_desc.width != desc.width || found_desc.height != desc.height)
|
||||
continue;
|
||||
|
||||
return It->second.second;
|
||||
}
|
||||
|
||||
image_view_type result = 0;
|
||||
if (!desc.is_cubemap)
|
||||
result = create_temporary_subresource_view(cmd, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height);
|
||||
else
|
||||
result = generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources);
|
||||
|
||||
if (result)
|
||||
{
|
||||
m_temporary_subresource_cache.insert({ desc.base_address,{ desc, result } });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void notify_surface_changed(u32 base_address)
|
||||
{
|
||||
m_temporary_subresource_cache.erase(base_address);
|
||||
}
|
||||
|
||||
template <typename render_target_type, typename surface_store_type>
|
||||
sampled_image_descriptor process_framebuffer_resource(render_target_type texptr, const u32 texaddr, const u32 gcm_format, surface_store_type& m_rtts,
|
||||
const u16 tex_width, const u16 tex_height, const rsx::texture_dimension_extended extended_dimension, const bool is_depth)
|
||||
|
|
@ -1046,7 +1081,7 @@ namespace rsx
|
|||
|
||||
if (can_cast)
|
||||
{
|
||||
sampled_image_descriptor desc = { texptr->get_surface(), format, 0, 0, surface_width, surface_height, texture_upload_context::framebuffer_storage,
|
||||
sampled_image_descriptor desc = { texptr->get_surface(), texaddr, format, 0, 0, surface_width, surface_height, texture_upload_context::framebuffer_storage,
|
||||
is_depth, 1.f, 1.f, rsx::texture_dimension_extended::texture_dimension_cubemap };
|
||||
|
||||
desc.set_external_cubemap_resources(image_array);
|
||||
|
|
@ -1139,7 +1174,7 @@ namespace rsx
|
|||
{
|
||||
const auto w = rsx::apply_resolution_scale(internal_width, true);
|
||||
const auto h = rsx::apply_resolution_scale(internal_height, true);
|
||||
return{ texptr->get_surface(), format, 0, 0, w, h, texture_upload_context::framebuffer_storage,
|
||||
return{ texptr->get_surface(), texaddr, format, 0, 0, w, h, texture_upload_context::framebuffer_storage,
|
||||
is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
|
||||
}
|
||||
|
||||
|
|
@ -1274,7 +1309,7 @@ namespace rsx
|
|||
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
|
||||
}
|
||||
|
||||
return{ rsc.surface->get_surface(), format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false),
|
||||
return{ rsc.surface->get_surface(), rsc.base_address, format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false),
|
||||
rsx::apply_resolution_scale(rsc.w, true), internal_height, texture_upload_context::framebuffer_storage,
|
||||
rsc.is_depth_surface, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
|
||||
}
|
||||
|
|
@ -1337,7 +1372,7 @@ namespace rsx
|
|||
|
||||
auto src_image = surface->get_raw_texture();
|
||||
f32 scale_y = (extended_dimension == rsx::texture_dimension_extended::texture_dimension_1d) ? 0.f : 1.f;
|
||||
return{ src_image, format, offset_x, offset_y, tex_width, tex_height, texture_upload_context::blit_engine_dst,
|
||||
return{ src_image, surface->get_section_base(), format, offset_x, offset_y, tex_width, tex_height, texture_upload_context::blit_engine_dst,
|
||||
surface->is_depth_texture(), 1.f, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
|
||||
}
|
||||
}
|
||||
|
|
@ -1686,6 +1721,7 @@ namespace rsx
|
|||
dst_area = dst_area * scale;
|
||||
|
||||
blitter.scale_image(vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit);
|
||||
notify_surface_changed(dst.rsx_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -334,7 +334,8 @@ void GLGSRender::end()
|
|||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
glBindTexture(target, m_gl_texture_cache.create_temporary_subresource(sampler_state->external_subresource_desc));
|
||||
void *unused = nullptr;
|
||||
glBindTexture(target, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
sampler_state->flag = false;
|
||||
}
|
||||
else
|
||||
|
|
@ -367,7 +368,8 @@ void GLGSRender::end()
|
|||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_gl_texture_cache.create_temporary_subresource(sampler_state->external_subresource_desc));
|
||||
void *unused = nullptr;
|
||||
glBindTexture(GL_TEXTURE_2D, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
sampler_state->flag = false;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -781,15 +781,6 @@ namespace gl
|
|||
m_hw_blitter.destroy();
|
||||
}
|
||||
|
||||
inline u32 create_temporary_subresource(deferred_subresource& desc)
|
||||
{
|
||||
void* unused = nullptr;
|
||||
if (!desc.is_cubemap)
|
||||
return create_temporary_subresource_view(unused, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height);
|
||||
else
|
||||
return generate_cubemap_from_images(unused, desc.gcm_format, desc.width, desc.external_cubemap_sources);
|
||||
}
|
||||
|
||||
bool is_depth_texture(const u32 rsx_address, const u32 rsx_size) override
|
||||
{
|
||||
reader_lock lock(m_cache_mutex);
|
||||
|
|
@ -824,6 +815,7 @@ namespace gl
|
|||
}
|
||||
|
||||
clear_temporary_subresources();
|
||||
m_temporary_subresource_cache.clear();
|
||||
}
|
||||
|
||||
bool blit(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool linear_interpolate, gl_render_targets& m_rtts)
|
||||
|
|
|
|||
|
|
@ -2424,6 +2424,7 @@ void VKGSRender::prepare_rtts()
|
|||
|
||||
surface->aa_mode = aa_mode;
|
||||
m_texture_cache.tag_framebuffer(surface_addresses[index]);
|
||||
m_texture_cache.notify_surface_changed(surface_addresses[index]);
|
||||
}
|
||||
|
||||
if (std::get<0>(m_rtts.m_bound_depth_stencil) != 0)
|
||||
|
|
@ -2440,6 +2441,7 @@ void VKGSRender::prepare_rtts()
|
|||
|
||||
ds->aa_mode = aa_mode;
|
||||
m_texture_cache.tag_framebuffer(zeta_address);
|
||||
m_texture_cache.notify_surface_changed(zeta_address);
|
||||
}
|
||||
|
||||
m_draw_buffers_count = static_cast<u32>(draw_buffers.size());
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ namespace vk
|
|||
//Stuff that has been dereferenced goes into these
|
||||
std::list<discarded_storage> m_discardable_storage;
|
||||
std::atomic<u32> m_discarded_memory_size = { 0 };
|
||||
|
||||
|
||||
void purge_cache()
|
||||
{
|
||||
for (auto &address_range : m_cache)
|
||||
|
|
@ -786,14 +786,6 @@ namespace vk
|
|||
purge_cache();
|
||||
}
|
||||
|
||||
inline vk::image_view* create_temporary_subresource(vk::command_buffer &cmd, deferred_subresource& desc)
|
||||
{
|
||||
if (!desc.is_cubemap)
|
||||
return create_temporary_subresource_view(cmd, desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height);
|
||||
else
|
||||
return generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources);
|
||||
}
|
||||
|
||||
bool is_depth_texture(const u32 rsx_address, const u32 rsx_size) override
|
||||
{
|
||||
reader_lock lock(m_cache_mutex);
|
||||
|
|
@ -849,6 +841,8 @@ namespace vk
|
|||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
m_temporary_subresource_cache.clear();
|
||||
}
|
||||
|
||||
template<typename RsxTextureType>
|
||||
|
|
|
|||
Loading…
Reference in a new issue