From e3f68c66d8aa8b990d1b4c7e04cc0697a82bd967 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 17 May 2019 00:03:37 +0300 Subject: [PATCH] rsx: Use a shared sampler pool instead of relying on the drivers --- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 17 ++------- rpcs3/Emu/RSX/VK/VKGSRender.h | 68 +++++++++++++++++++++++++++++++-- rpcs3/Emu/RSX/VK/VKHelpers.h | 1 - 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index f2f1ed60f9..5e8e069f77 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -775,7 +775,6 @@ VKGSRender::~VKGSRender() } m_aux_frame_context.buffer_views_to_clean.clear(); - m_aux_frame_context.samplers_to_clean.clear(); //NOTE: aux_context uses descriptor pools borrowed from the main queues and any allocations will be automatically freed when pool is destroyed for (auto &ctx : frame_context_storage) @@ -784,7 +783,6 @@ VKGSRender::~VKGSRender() ctx.descriptor_pool.destroy(); ctx.buffer_views_to_clean.clear(); - ctx.samplers_to_clean.clear(); } m_draw_fbo.reset(); @@ -798,13 +796,7 @@ VKGSRender::~VKGSRender() m_rtts.destroy(); m_texture_cache.destroy(); - //Sampler handles - for (auto& handle : fs_sampler_handles) - handle.reset(); - - for (auto& handle : vs_sampler_handles) - handle.reset(); - + m_resource_manager.destroy(); m_stencil_mirror_sampler.reset(); //Overlay text handler @@ -1594,14 +1586,13 @@ void VKGSRender::end() if (!fs_sampler_handles[i]->matches(wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod, min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode)) { - m_current_frame->samplers_to_clean.push_back(std::move(fs_sampler_handles[i])); replace = true; } } if (replace) { - fs_sampler_handles[i] = std::make_unique(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod, + fs_sampler_handles[i] = m_resource_manager.find_sampler(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod, min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode); } } @@ -1641,14 +1632,13 @@ void VKGSRender::end() if (!vs_sampler_handles[i]->matches(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, unnormalized_coords, 0.f, 1.f, min_lod, max_lod, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, border_color)) { - m_current_frame->samplers_to_clean.push_back(std::move(vs_sampler_handles[i])); replace = true; } } if (replace) { - vs_sampler_handles[i] = std::make_unique( + vs_sampler_handles[i] = m_resource_manager.find_sampler( *m_device, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, unnormalized_coords, @@ -2506,7 +2496,6 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources) m_ui_renderer->free_resources(); ctx->buffer_views_to_clean.clear(); - ctx->samplers_to_clean.clear(); if (ctx->last_frame_sync_time > m_last_heap_sync_time) { diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 9aba5bd3b6..a15489e3d5 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -164,7 +164,6 @@ struct frame_context_t u32 used_descriptors = 0; std::vector> buffer_views_to_clean; - std::vector> samplers_to_clean; u32 present_image = UINT32_MAX; command_buffer_chunk* swap_command_buffer = nullptr; @@ -205,7 +204,6 @@ struct frame_context_t void swap_storage(frame_context_t &other) { std::swap(buffer_views_to_clean, other.buffer_views_to_clean); - std::swap(samplers_to_clean, other.samplers_to_clean); } void tag_frame_end(s64 attrib_loc, s64 vtxenv_loc, s64 fragenv_loc, s64 vtxlayout_loc, s64 fragtex_loc, s64 fragconst_loc,s64 vtxconst_loc, s64 index_loc, s64 texture_loc) @@ -279,6 +277,66 @@ struct flush_request_task } }; +// TODO: This class will be expanded into a global allocator/collector eventually +class resource_manager +{ +private: + std::unordered_multimap> m_sampler_pool; + + bool value_compare(const f32& a, const f32& b) + { + return fabsf(a - b) < 0.0000001f; + } + +public: + + resource_manager() {} + ~resource_manager() {} + + void destroy() + { + m_sampler_pool.clear(); + } + + vk::sampler* find_sampler(VkDevice dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w, + VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod, + VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color, + VkBool32 depth_compare = VK_FALSE, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER) + { + u64 key = u16(clamp_u) | u64(clamp_v) << 3 | u64(clamp_w) << 6; + key |= u64(unnormalized_coordinates) << 9; // 1 bit + key |= u64(min_filter) << 10 | u64(mag_filter) << 11; // 1 bit each + key |= u64(mipmap_mode) << 12; // 1 bit + key |= u64(border_color) << 13; // 3 bits + key |= u64(depth_compare) << 16; // 1 bit + key |= u64(depth_compare_mode) << 17; // 3 bits + + const auto found = m_sampler_pool.equal_range(key); + for (auto It = found.first; It != found.second; ++It) + { + const auto& info = It->second->info; + if (!value_compare(info.mipLodBias, mipLodBias) || + !value_compare(info.maxAnisotropy, max_anisotropy) || + !value_compare(info.minLod, min_lod) || + !value_compare(info.maxLod, max_lod)) + { + continue; + } + + return It->second.get(); + } + + auto result = std::make_unique( + dev, clamp_u, clamp_v, clamp_w, unnormalized_coordinates, + mipLodBias, max_anisotropy, min_lod, max_lod, + min_filter, mag_filter, mipmap_mode, border_color, + depth_compare, depth_compare_mode); + + auto It = m_sampler_pool.emplace(key, std::move(result)); + return It->second.get(); + } +}; + class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control { private: @@ -303,12 +361,14 @@ private: std::unique_ptr m_stencil_mirror_sampler; std::array, rsx::limits::fragment_textures_count> fs_sampler_state = {}; std::array, rsx::limits::vertex_textures_count> vs_sampler_state = {}; - std::array, rsx::limits::fragment_textures_count> fs_sampler_handles; - std::array, rsx::limits::vertex_textures_count> vs_sampler_handles; + std::array fs_sampler_handles{}; + std::array vs_sampler_handles{}; std::unique_ptr m_persistent_attribute_storage; std::unique_ptr m_volatile_attribute_storage; + resource_manager m_resource_manager; + public: //vk::fbo draw_fbo; std::unique_ptr m_vertex_cache; diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 839d7f84f9..66c758926b 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1364,7 +1364,6 @@ namespace vk VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER) : m_device(dev) { - VkSamplerCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; info.addressModeU = clamp_u; info.addressModeV = clamp_v;