diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 13124c2f56..a9f612ca8b 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -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 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 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 images) + { + external_subresource_desc.external_cubemap_sources = images; + external_subresource_desc.is_cubemap = true; + } + }; + + protected: struct ranged_storage { std::vector data; //Stored data @@ -178,6 +248,7 @@ namespace rsx shared_mutex m_cache_mutex; std::unordered_map m_cache; + std::unordered_multimap> m_temporary_subresource_cache; std::atomic 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 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 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 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 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; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index ddf142cc06..33867d09dd 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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 diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 412e215f0c..4e5170a719 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -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) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 9bf89d4726..4881d523f0 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -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(draw_buffers.size()); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 39768fd386..b4d2e004e0 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -411,7 +411,7 @@ namespace vk //Stuff that has been dereferenced goes into these std::list m_discardable_storage; std::atomic 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