Skip to content

Commit

Permalink
vk: Use image hot-cache for faster allocation times
Browse files Browse the repository at this point in the history
  • Loading branch information
cipherxof committed Apr 15, 2022
1 parent 73deba6 commit 7620201
Show file tree
Hide file tree
Showing 10 changed files with 758 additions and 620 deletions.
6 changes: 5 additions & 1 deletion rpcs3/Emu/RSX/Common/TextureUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ namespace rsx
{
read = 0,
write = 1,
transfer = 2
transfer = 2,

gpu_reference = (1 << 6)
};

enum format_type : u8
Expand All @@ -57,6 +59,8 @@ namespace rsx
rsx::texture_dimension_extended image_type = texture_dimension_extended::texture_dimension_2d;
rsx::format_type format_class = rsx::format_type::color;
bool is_cyclic_reference = false;
u32 ref_address = 0;
u64 surface_cache_tag = 0;
f32 scale_x = 1.f;
f32 scale_y = 1.f;

Expand Down
9 changes: 0 additions & 9 deletions rpcs3/Emu/RSX/Common/surface_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -837,8 +837,6 @@ namespace rsx
{
invalidate(It->second);
m_render_targets_storage.erase(It);

cache_tag = rsx::get_shared_tag();
return;
}
}
Expand All @@ -849,8 +847,6 @@ namespace rsx
{
invalidate(It->second);
m_depth_stencil_storage.erase(It);

cache_tag = rsx::get_shared_tag();
return;
}
}
Expand Down Expand Up @@ -1072,11 +1068,6 @@ namespace rsx
}
}

void notify_memory_structure_changed()
{
cache_tag = rsx::get_shared_tag();
}

void invalidate_all()
{
// Unbind and invalidate all resources
Expand Down
130 changes: 128 additions & 2 deletions rpcs3/Emu/RSX/Common/texture_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,65 @@ namespace rsx
{
return (image_handle || external_subresource_desc.op != deferred_request_command::nop);
}

/**
* Returns a boolean true/false if the descriptor is expired
* Optionally returns a second variable that contains the surface reference.
* The surface reference can be used to insert a texture barrier or inject a deferred resource
*/
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)
{
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;
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 (!(surface = surface_cache.get_surface_at(ref_address)))
{
// Compositing op. Just ignore expiry for now
verify(HERE), !ref_image;
return {};
}
}

verify(HERE), surface;
if (!ref_image || surface->get_surface(rsx::surface_access::gpu_reference) == ref_image)
{
// Same image, so configuration did not change.
if (surface_cache.cache_tag <= surface_cache_tag &&
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 };
}
};


Expand Down Expand Up @@ -320,7 +379,7 @@ namespace rsx
const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) = 0;
virtual section_storage_type* create_nul_section(commandbuffer_type&, const address_range &rsx_range, bool memory_load) = 0;
virtual void enforce_surface_creation_type(section_storage_type& section, u32 gcm_format, texture_create_flags expected) = 0;
virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0;
virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex, bool strong_ordering = true) = 0;
virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& remap_vector) = 0;
virtual image_view_type generate_3d_from_2d_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& remap_vector) = 0;
virtual image_view_type generate_atlas_from_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy, const texture_channel_remap_t& remap_vector) = 0;
Expand Down Expand Up @@ -1707,6 +1766,71 @@ namespace rsx
return {};
}

template <typename surface_store_type, typename RsxTextureType>
bool test_if_descriptor_expired(commandbuffer_type& cmd, surface_store_type& surface_cache, sampled_image_descriptor* descriptor, const RsxTextureType& tex)
{
auto result = descriptor->is_expired(surface_cache);
if (result.second && descriptor->is_cyclic_reference)
{
/* NOTE: All cyclic descriptors updated via fast update must have a barrier check
* It is possible for the following sequence of events to break common-sense tests
* 1. Cyclic ref occurs normally in upload_texture
* 2. Surface is swappd out, but texture is not updated
* 3. Surface is swapped back in. Surface cache resets layout to optimal rasterization layout
* 4. During bind, the surface is converted to shader layout because it is not in GENERAL layout
*/
if (!g_cfg.video.strict_rendering_mode)
{
insert_texture_barrier(cmd, result.second, false);
}
else if (descriptor->image_handle)
{
// Rebuild duplicate surface
auto src = descriptor->image_handle->image();
rsx::image_section_attributes_t attr;
attr.address = descriptor->ref_address;
attr.gcm_format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
attr.width = src->width();
attr.height = src->height();
attr.depth = 1;
//attr.mipmaps = 1;
attr.pitch = 0; // Unused
attr.slice_h = src->height();
attr.bpp = get_format_block_size_in_bytes(attr.gcm_format);
//attr.swizzled = false;

// Sanity checks
const bool gcm_format_is_depth = helpers::is_gcm_depth_format(attr.gcm_format);
const bool bound_surface_is_depth = surface_cache.m_bound_depth_stencil.first == attr.address;
if (!gcm_format_is_depth && bound_surface_is_depth)
{
// While the copy routines can perform a typeless cast, prefer to not cross the aspect barrier if possible
// This avoids messing with other solutions such as texture redirection as well
attr.gcm_format = helpers::get_compatible_depth_format(attr.gcm_format);
}

descriptor->external_subresource_desc =
{
src,
rsx::deferred_request_command::copy_image_dynamic,
attr,
{},
rsx::default_remap_vector
};

descriptor->external_subresource_desc.do_not_cache = true;
descriptor->image_handle = nullptr;
}
else
{
// Force reupload
return true;
}
}

return result.first;
}

template <typename RsxTextureType, typename surface_store_type, typename ...Args>
sampled_image_descriptor upload_texture(commandbuffer_type& cmd, RsxTextureType& tex, surface_store_type& m_rtts, Args&&... extras)
{
Expand Down Expand Up @@ -1805,6 +1929,9 @@ namespace rsx
result.external_subresource_desc.cache_range = lookup_range;
}

result.ref_address = attributes.address;
result.surface_cache_tag = m_rtts.cache_tag;

if (subsurface_count == 1)
{
return result;
Expand Down Expand Up @@ -2650,7 +2777,6 @@ namespace rsx
// NOTE: This doesn't work very well in case of Cell access
// Need to lock the affected memory range and actually attach this subres to a locked_region
dst_subres.surface->on_write_copy(rsx::get_shared_tag());
m_rtts.notify_memory_structure_changed();

// Reset this object's synchronization status if it is locked
lock.upgrade();
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/GL/GLTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ namespace gl
section.set_view_flags(flags);
}

void insert_texture_barrier(gl::command_context&, gl::texture*) override
void insert_texture_barrier(gl::command_context&, gl::texture*, bool) override
{
auto &caps = gl::get_driver_caps();

Expand Down
Loading

0 comments on commit 7620201

Please sign in to comment.