diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index fb06a2859c..4c34dd3159 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -796,3 +796,17 @@ size_t get_texture_size(const rsx::vertex_texture &texture) return get_texture_size(texture.format(), texture.width(), texture.height(), texture.depth(), texture.pitch(), texture.get_exact_mipmap_count(), texture.cubemap() ? 6 : 1); } + +u32 get_remap_encoding(const std::pair, std::array>& remap) +{ + u32 encode = 0; + encode |= (remap.first[0] << 0); + encode |= (remap.first[1] << 2); + encode |= (remap.first[2] << 4); + encode |= (remap.first[3] << 6); + encode |= (remap.second[0] << 8); + encode |= (remap.second[1] << 10); + encode |= (remap.second[2] << 12); + encode |= (remap.second[3] << 14); + return encode; +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index c82d8a8181..dfefc23070 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -139,3 +139,8 @@ size_t get_texture_size(const rsx::vertex_texture &texture); * Get packed pitch */ u32 get_format_packed_pitch(u32 format, u16 width); + +/** +* Reverse encoding +*/ +u32 get_remap_encoding(const std::pair, std::array>& remap); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index ba96190784..9943b69964 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1298,11 +1298,19 @@ private: } } - VkComponentMapping real_mapping = vk::apply_swizzle_remap - ( - {native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b }, - remap - ); + VkComponentMapping real_mapping; + if (remap_encoding == 0xAAE4) + { + real_mapping = native_component_map; + } + else + { + real_mapping = vk::apply_swizzle_remap + ( + { native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b }, + remap + ); + } const auto range = vk::get_image_subresource_range(0, 0, info.arrayLayers, info.mipLevels, aspect() & mask); diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index e382bdf0d6..3dbd058b4e 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -138,7 +138,7 @@ namespace vk return fs_inputs; } - virtual void get_dynamic_state_entries(VkDynamicState* state_descriptors, VkPipelineDynamicStateCreateInfo& info) + virtual void get_dynamic_state_entries(VkDynamicState* /*state_descriptors*/, VkPipelineDynamicStateCreateInfo& /*info*/) {} virtual std::vector get_push_constants() diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 2b64df4e3a..49319f65bf 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -292,7 +292,7 @@ namespace vk verify(HERE), miss; // Replace the wait event with a new one to avoid premature signaling! - vk::get_resource_manager->dispose(dma_fence); + vk::get_resource_manager()->dispose(dma_fence); VkEventCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; @@ -369,35 +369,22 @@ namespace vk } }; - struct discarded_storage + struct temporary_storage { std::unique_ptr combined_image; - std::unique_ptr view; - std::unique_ptr img; - //Memory held by this temp storage object + // Memory held by this temp storage object u32 block_size = 0; - //Frame id tag + // Frame id tag const u64 frame_tag = vk::get_current_frame_id(); - discarded_storage(std::unique_ptr& _view) + temporary_storage(std::unique_ptr& _img) { - view = std::move(_view); + combined_image = std::move(_img); } - discarded_storage(std::unique_ptr& _img) - { - img = std::move(_img); - } - - discarded_storage(std::unique_ptr& _img, std::unique_ptr& _view) - { - img = std::move(_img); - view = std::move(_view); - } - - discarded_storage(vk::cached_texture_section& tex) + temporary_storage(vk::cached_texture_section& tex) { combined_image = std::move(tex.get_texture()); block_size = tex.get_section_size(); @@ -407,6 +394,21 @@ namespace vk { return ref_frame > 0 && frame_tag <= ref_frame; } + + bool matches(VkFormat format, u16 w, u16 h, u16 d, VkFlags flags) const + { + if (combined_image && + combined_image->info.flags == flags && + combined_image->format() == format && + combined_image->width() == w && + combined_image->height() == h && + combined_image->depth() == d) + { + return true; + } + + return false; + } }; class texture_cache : public rsx::texture_cache @@ -420,8 +422,8 @@ namespace vk { if (tex.is_managed()) { - m_discarded_memory_size += tex.get_section_size(); - m_discardable_storage.emplace_back(tex); + m_temporary_memory_size += tex.get_section_size(); + m_temporary_storage.emplace_back(tex); } } @@ -435,15 +437,15 @@ namespace vk vk::data_heap* m_texture_upload_heap; //Stuff that has been dereferenced goes into these - std::list m_discardable_storage; - std::atomic m_discarded_memory_size = { 0 }; + std::list m_temporary_storage; + std::atomic m_temporary_memory_size = { 0 }; void clear() { baseclass::clear(); - m_discardable_storage.clear(); - m_discarded_memory_size = 0; + m_temporary_storage.clear(); + m_temporary_memory_size = 0; } VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const texture_channel_remap_t& remap_vector) const @@ -678,22 +680,64 @@ namespace vk return result; } + std::unique_ptr find_temporary_image(VkFormat format, u16 w, u16 h, u16 d) + { + const auto current_frame = vk::get_current_frame_id(); + for (auto &e : m_temporary_storage) + { + if (e.frame_tag != current_frame && e.matches(format, w, h, d, 0)) + { + m_temporary_memory_size -= e.block_size; + e.block_size = 0; + return std::move(e.combined_image); + } + } + + return {}; + } + + std::unique_ptr find_temporary_cubemap(VkFormat format, u16 size) + { + const auto current_frame = vk::get_current_frame_id(); + for (auto &e : m_temporary_storage) + { + if (e.frame_tag != current_frame && e.matches(format, size, size, 1, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) + { + m_temporary_memory_size -= e.block_size; + e.block_size = 0; + return std::move(e.combined_image); + } + } + + return {}; + } + protected: vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector, bool copy) { - std::unique_ptr image; - std::unique_ptr view; + std::unique_ptr image; VkImageCreateFlags image_flags = (view_type == VK_IMAGE_VIEW_TYPE_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); - VkImageAspectFlags aspect = vk::get_aspect_flags(dst_format); - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - image_type, - dst_format, - w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags); + if (LIKELY(!image_flags)) + { + image = find_temporary_image(dst_format, w, h, 1); + } + else + { + image = find_temporary_cubemap(dst_format, w); + } + + if (!image) + { + image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + image_type, + dst_format, + w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags); + } //This method is almost exclusively used to work on framebuffer resources //Keep the original swizzle layout unless there is data format conversion @@ -711,12 +755,8 @@ namespace vk view_swizzle = source->native_component_map; } - if (memcmp(remap_vector.first.data(), rsx::default_remap_vector.first.data(), 4) || - memcmp(remap_vector.second.data(), rsx::default_remap_vector.second.data(), 4)) - view_swizzle = vk::apply_swizzle_remap({view_swizzle.a, view_swizzle.r, view_swizzle.g, view_swizzle.b}, remap_vector); - - VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 }; - view = std::make_unique(*vk::get_current_renderer(), image.get(), view_swizzle, view_range); + image->set_native_component_layout(view_swizzle); + auto view = image->get_view(get_remap_encoding(remap_vector), remap_vector); if (copy) { @@ -734,11 +774,11 @@ namespace vk } const u32 resource_memory = w * h * 4; //Rough approximate - m_discardable_storage.emplace_back(image, view); - m_discardable_storage.back().block_size = resource_memory; - m_discarded_memory_size += resource_memory; + m_temporary_storage.emplace_back(image); + m_temporary_storage.back().block_size = resource_memory; + m_temporary_memory_size += resource_memory; - return m_discardable_storage.back().view.get(); + return view; } vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format, @@ -757,20 +797,20 @@ namespace vk vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size, const std::vector& sections_to_copy, const texture_channel_remap_t& /*remap_vector*/) override { - std::unique_ptr image; - std::unique_ptr view; - + std::unique_ptr image; VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format); - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_IMAGE_TYPE_2D, - dst_format, - size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT); + if (image = find_temporary_cubemap(dst_format, size); !image) + { + image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + VK_IMAGE_TYPE_2D, + dst_format, + size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT); + } - VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 6 }; - view = std::make_unique(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range); + auto view = image->get_view(0xAAE4, rsx::default_remap_vector); VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 6 }; vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); @@ -791,30 +831,30 @@ namespace vk vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); const u32 resource_memory = size * size * 6 * 4; //Rough approximate - m_discardable_storage.emplace_back(image, view); - m_discardable_storage.back().block_size = resource_memory; - m_discarded_memory_size += resource_memory; + m_temporary_storage.emplace_back(image); + m_temporary_storage.back().block_size = resource_memory; + m_temporary_memory_size += resource_memory; - return m_discardable_storage.back().view.get(); + return view; } vk::image_view* generate_3d_from_2d_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector& sections_to_copy, const texture_channel_remap_t& /*remap_vector*/) override { - std::unique_ptr image; - std::unique_ptr view; - + std::unique_ptr image; VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format); - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_IMAGE_TYPE_3D, - dst_format, - width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0); + if (image = find_temporary_image(dst_format, width, height, depth); !image) + { + image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + VK_IMAGE_TYPE_3D, + dst_format, + width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0); + } - VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 }; - view = std::make_unique(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range); + auto view = image->get_view(0xAAE4, rsx::default_remap_vector); VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 1 }; vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); @@ -835,11 +875,11 @@ namespace vk vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); const u32 resource_memory = width * height * depth * 4; //Rough approximate - m_discardable_storage.emplace_back(image, view); - m_discardable_storage.back().block_size = resource_memory; - m_discarded_memory_size += resource_memory; + m_temporary_storage.emplace_back(image); + m_temporary_storage.back().block_size = resource_memory; + m_temporary_memory_size += resource_memory; - return m_discardable_storage.back().view.get(); + return view; } vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, @@ -1189,17 +1229,17 @@ namespace vk void on_frame_end() override { if (m_storage.m_unreleased_texture_objects >= m_max_zombie_objects || - m_discarded_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources + m_temporary_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources { purge_unreleased_sections(); } const u64 last_complete_frame = vk::get_last_completed_frame_id(); - m_discardable_storage.remove_if([&](const discarded_storage& o) + m_temporary_storage.remove_if([&](const temporary_storage& o) { - if (o.test(last_complete_frame)) + if (!o.block_size || o.test(last_complete_frame)) { - m_discarded_memory_size -= o.block_size; + m_temporary_memory_size -= o.block_size; return true; } return false; @@ -1219,7 +1259,7 @@ namespace vk } // Uploads a linear memory range as a BGRA8 texture - auto image = std::make_unique(*m_device, m_memory_types.host_visible_coherent, + auto image = std::make_unique(*m_device, m_memory_types.host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_B8G8R8A8_UNORM, @@ -1257,9 +1297,9 @@ namespace vk auto result = image.get(); const u32 resource_memory = width * height * 4; //Rough approximate - m_discardable_storage.emplace_back(image); - m_discardable_storage.back().block_size = resource_memory; - m_discarded_memory_size += resource_memory; + m_temporary_storage.emplace_back(image); + m_temporary_storage.back().block_size = resource_memory; + m_temporary_memory_size += resource_memory; return result; } @@ -1284,12 +1324,12 @@ namespace vk const u32 get_unreleased_textures_count() const override { - return baseclass::get_unreleased_textures_count() + (u32)m_discardable_storage.size(); + return baseclass::get_unreleased_textures_count() + (u32)m_temporary_storage.size(); } const u32 get_temporary_memory_in_use() { - return m_discarded_memory_size; + return m_temporary_memory_size; } }; }