1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

vk: Reimplement sampler caching to take border color into account

This commit is contained in:
kd-11 2023-05-22 20:13:24 +03:00 committed by kd-11
parent 7eb730ee03
commit 75da7d80dc
6 changed files with 159 additions and 47 deletions

View File

@ -54,6 +54,7 @@ namespace vk
ensure(max_allowed_samplers);
rsx_log.warning("Trimming allocated samplers. Allocated = %u, Max = %u", allocated_sampler_count, limits.maxSamplerAllocationCount);
#if 0
for (auto It = m_sampler_pool.begin(); It != m_sampler_pool.end();)
{
if (!It->second->has_refs())
@ -65,6 +66,7 @@ namespace vk
++It;
}
#endif
}
}

View File

@ -86,12 +86,8 @@ namespace vk
class resource_manager
{
private:
struct cached_sampler_object_t : public vk::sampler, public rsx::ref_counted
{
using vk::sampler::sampler;
};
sampler_pool_t m_sampler_pool;
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
std::deque<eid_scope_t> m_eid_map;
shared_mutex m_eid_map_lock;
@ -108,28 +104,6 @@ namespace vk
return m_eid_map.back();
}
template<bool _signed = false>
u16 encode_fxp(f32 value)
{
u16 raw = u16(std::abs(value) * 256.);
if constexpr (!_signed)
{
return raw;
}
else
{
if (value >= 0.f) [[likely]]
{
return raw;
}
else
{
return u16(0 - raw) & 0x1fff;
}
}
}
public:
resource_manager() = default;
@ -144,20 +118,14 @@ namespace vk
vk::sampler* get_sampler(const vk::render_device& dev, vk::sampler* previous,
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,
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, const vk::border_color_t& 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
key |= u64(encode_fxp(min_lod)) << 20; // 12 bits
key |= u64(encode_fxp(max_lod)) << 32; // 12 bits
key |= u64(encode_fxp<true>(mipLodBias)) << 44; // 13 bits
key |= u64(max_anisotropy) << 57; // 4 bits
const auto key = m_sampler_pool.compute_storage_key(
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);
if (previous)
{
@ -166,11 +134,9 @@ namespace vk
as_cached_object->release();
}
if (const auto found = m_sampler_pool.find(key);
found != m_sampler_pool.end())
if (const auto found = m_sampler_pool.find(key))
{
found->second->add_ref();
return found->second.get();
return found;
}
auto result = std::make_unique<cached_sampler_object_t>(
@ -179,9 +145,9 @@ namespace vk
min_filter, mag_filter, mipmap_mode, border_color,
depth_compare, depth_compare_mode);
auto It = m_sampler_pool.emplace(key, std::move(result));
auto ret = It.first->second.get();
ret->add_ref();
result->add_ref();
auto ret = result.get();
m_sampler_pool.emplace(key, result);
return ret;
}

View File

@ -167,7 +167,7 @@ namespace vk
bool get_descriptor_indexing_support() const { return pgpu->descriptor_indexing_support; }
bool get_framebuffer_loops_support() const { return pgpu->optional_features_support.framebuffer_loops; }
bool get_barycoords_support() const { return pgpu->optional_features_support.barycentric_coords; }
bool get_custom_border_color_support() const { pgpu->optional_features_support.custom_border_color; }
bool get_custom_border_color_support() const { return pgpu->optional_features_support.custom_border_color; }
u64 get_descriptor_update_after_bind_support() const { return pgpu->descriptor_indexing_support.update_after_bind_mask; }
u32 get_descriptor_max_draw_calls() const { return pgpu->descriptor_max_draw_calls; }

View File

@ -21,6 +21,7 @@ namespace vk
}
border_color_t::border_color_t(u32 encoded_color)
: storage_key(0)
{
value = vk::get_border_color(encoded_color);
@ -34,7 +35,10 @@ namespace vk
if (!g_render_device->get_custom_border_color_support())
{
value = get_closest_border_color_enum(color_value);
return;
}
storage_key = encoded_color;
}
sampler::sampler(const vk::render_device& dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
@ -98,4 +102,88 @@ namespace vk
return true;
}
sampler_pool_key_t sampler_pool_t::compute_storage_key(
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, const vk::border_color_t& border_color,
VkBool32 depth_compare, VkCompareOp depth_compare_mode)
{
sampler_pool_key_t key{};
bool use_border_encoding = false;
if (border_color.value > VK_BORDER_COLOR_INT_OPAQUE_WHITE)
{
// If there is no clamp to border in use, we can ignore the border color entirely
if (clamp_u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
clamp_v == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
clamp_w == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
{
use_border_encoding = true;
}
}
key.base_key = u16(clamp_u) | u64(clamp_v) << 3 | u64(clamp_w) << 6;
key.base_key |= u64(unnormalized_coordinates) << 9; // 1 bit
key.base_key |= u64(min_filter) << 10 | u64(mag_filter) << 11; // 1 bit each
key.base_key |= u64(mipmap_mode) << 12; // 1 bit
if (!use_border_encoding)
{
// Bits 13-16 are reserved for border color encoding
key.base_key |= u64(border_color.value) << 13;
}
else
{
key.border_color_key = border_color.storage_key;
}
key.base_key |= u64(depth_compare) << 16; // 1 bit
key.base_key |= u64(depth_compare_mode) << 17; // 3 bits
key.base_key |= u64(rsx::encode_fx12(min_lod)) << 20; // 12 bits
key.base_key |= u64(rsx::encode_fx12(max_lod)) << 32; // 12 bits
key.base_key |= u64(rsx::encode_fx12<true>(mipLodBias)) << 44; // 13 bits (fx12 + sign)
key.base_key |= u64(max_anisotropy) << 57; // 4 bits
return key;
}
void sampler_pool_t::clear()
{
m_generic_sampler_pool.clear();
m_custom_color_sampler_pool.clear();
}
vk::sampler* sampler_pool_t::find(const sampler_pool_key_t& key) const
{
if (!key.border_color_key) [[ likely ]]
{
const auto found = m_generic_sampler_pool.find(key.base_key);
return found == m_generic_sampler_pool.end() ? nullptr : found->second.get();
}
const auto block = m_custom_color_sampler_pool.equal_range(key.base_key);
for (auto It = block.first; It != block.second; ++It)
{
if (It->second->key.border_color_key == key.border_color_key)
{
return It->second.get();
}
}
return nullptr;
}
void sampler_pool_t::emplace(const sampler_pool_key_t& key, std::unique_ptr<cached_sampler_object_t>& object)
{
object->key = key;
if (!key.border_color_key) [[ likely ]]
{
m_generic_sampler_pool.emplace(key.base_key, std::move(object));
return;
}
m_custom_color_sampler_pool.emplace (key.base_key, std::move(object));
}
}

View File

@ -7,6 +7,7 @@ namespace vk
{
struct border_color_t
{
u32 storage_key;
VkBorderColor value;
color4f color_value;
@ -50,4 +51,37 @@ namespace vk
private:
VkDevice m_device;
};
// Caching helpers
struct sampler_pool_key_t
{
u64 base_key;
u32 border_color_key;
};
struct cached_sampler_object_t : public vk::sampler, public rsx::ref_counted
{
sampler_pool_key_t key;
using vk::sampler::sampler;
};
class sampler_pool_t
{
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_generic_sampler_pool;
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_custom_color_sampler_pool;
public:
sampler_pool_key_t compute_storage_key(
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, const vk::border_color_t& border_color,
VkBool32 depth_compare, VkCompareOp depth_compare_mode);
void clear();
vk::sampler* find(const sampler_pool_key_t& key) const;
void emplace(const sampler_pool_key_t& key, std::unique_ptr<cached_sampler_object_t>& object);
};
}

View File

@ -914,4 +914,26 @@ namespace rsx
return base * scale;
}
template<bool _signed = false>
u16 encode_fx12(f32 value)
{
u16 raw = u16(std::abs(value) * 256.);
if constexpr (!_signed)
{
return raw;
}
else
{
if (value >= 0.f) [[likely]]
{
return raw;
}
else
{
return u16(0 - raw) & 0x1fff;
}
}
}
}