mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
vk: Reimplement sampler caching to take border color into account
This commit is contained in:
parent
7eb730ee03
commit
75da7d80dc
@ -54,6 +54,7 @@ namespace vk
|
|||||||
ensure(max_allowed_samplers);
|
ensure(max_allowed_samplers);
|
||||||
rsx_log.warning("Trimming allocated samplers. Allocated = %u, Max = %u", allocated_sampler_count, limits.maxSamplerAllocationCount);
|
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();)
|
for (auto It = m_sampler_pool.begin(); It != m_sampler_pool.end();)
|
||||||
{
|
{
|
||||||
if (!It->second->has_refs())
|
if (!It->second->has_refs())
|
||||||
@ -65,6 +66,7 @@ namespace vk
|
|||||||
|
|
||||||
++It;
|
++It;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,12 +86,8 @@ namespace vk
|
|||||||
class resource_manager
|
class resource_manager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct cached_sampler_object_t : public vk::sampler, public rsx::ref_counted
|
sampler_pool_t m_sampler_pool;
|
||||||
{
|
|
||||||
using vk::sampler::sampler;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
|
|
||||||
std::deque<eid_scope_t> m_eid_map;
|
std::deque<eid_scope_t> m_eid_map;
|
||||||
shared_mutex m_eid_map_lock;
|
shared_mutex m_eid_map_lock;
|
||||||
|
|
||||||
@ -108,28 +104,6 @@ namespace vk
|
|||||||
return m_eid_map.back();
|
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:
|
public:
|
||||||
|
|
||||||
resource_manager() = default;
|
resource_manager() = default;
|
||||||
@ -144,20 +118,14 @@ namespace vk
|
|||||||
vk::sampler* get_sampler(const vk::render_device& dev, vk::sampler* previous,
|
vk::sampler* get_sampler(const vk::render_device& dev, vk::sampler* previous,
|
||||||
VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
|
VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
|
||||||
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
|
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)
|
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;
|
const auto key = m_sampler_pool.compute_storage_key(
|
||||||
key |= u64(unnormalized_coordinates) << 9; // 1 bit
|
clamp_u, clamp_v, clamp_w,
|
||||||
key |= u64(min_filter) << 10 | u64(mag_filter) << 11; // 1 bit each
|
unnormalized_coordinates, mipLodBias, max_anisotropy, min_lod, max_lod,
|
||||||
key |= u64(mipmap_mode) << 12; // 1 bit
|
min_filter, mag_filter, mipmap_mode, border_color,
|
||||||
key |= u64(border_color) << 13; // 3 bits
|
depth_compare, depth_compare_mode);
|
||||||
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
|
|
||||||
|
|
||||||
if (previous)
|
if (previous)
|
||||||
{
|
{
|
||||||
@ -166,11 +134,9 @@ namespace vk
|
|||||||
as_cached_object->release();
|
as_cached_object->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto found = m_sampler_pool.find(key);
|
if (const auto found = m_sampler_pool.find(key))
|
||||||
found != m_sampler_pool.end())
|
|
||||||
{
|
{
|
||||||
found->second->add_ref();
|
return found;
|
||||||
return found->second.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = std::make_unique<cached_sampler_object_t>(
|
auto result = std::make_unique<cached_sampler_object_t>(
|
||||||
@ -179,9 +145,9 @@ namespace vk
|
|||||||
min_filter, mag_filter, mipmap_mode, border_color,
|
min_filter, mag_filter, mipmap_mode, border_color,
|
||||||
depth_compare, depth_compare_mode);
|
depth_compare, depth_compare_mode);
|
||||||
|
|
||||||
auto It = m_sampler_pool.emplace(key, std::move(result));
|
result->add_ref();
|
||||||
auto ret = It.first->second.get();
|
auto ret = result.get();
|
||||||
ret->add_ref();
|
m_sampler_pool.emplace(key, result);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ namespace vk
|
|||||||
bool get_descriptor_indexing_support() const { return pgpu->descriptor_indexing_support; }
|
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_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_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; }
|
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; }
|
u32 get_descriptor_max_draw_calls() const { return pgpu->descriptor_max_draw_calls; }
|
||||||
|
@ -21,6 +21,7 @@ namespace vk
|
|||||||
}
|
}
|
||||||
|
|
||||||
border_color_t::border_color_t(u32 encoded_color)
|
border_color_t::border_color_t(u32 encoded_color)
|
||||||
|
: storage_key(0)
|
||||||
{
|
{
|
||||||
value = vk::get_border_color(encoded_color);
|
value = vk::get_border_color(encoded_color);
|
||||||
|
|
||||||
@ -34,7 +35,10 @@ namespace vk
|
|||||||
if (!g_render_device->get_custom_border_color_support())
|
if (!g_render_device->get_custom_border_color_support())
|
||||||
{
|
{
|
||||||
value = get_closest_border_color_enum(color_value);
|
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,
|
sampler::sampler(const vk::render_device& dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
|
||||||
@ -98,4 +102,88 @@ namespace vk
|
|||||||
|
|
||||||
return true;
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ namespace vk
|
|||||||
{
|
{
|
||||||
struct border_color_t
|
struct border_color_t
|
||||||
{
|
{
|
||||||
|
u32 storage_key;
|
||||||
VkBorderColor value;
|
VkBorderColor value;
|
||||||
color4f color_value;
|
color4f color_value;
|
||||||
|
|
||||||
@ -50,4 +51,37 @@ namespace vk
|
|||||||
private:
|
private:
|
||||||
VkDevice m_device;
|
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);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -914,4 +914,26 @@ namespace rsx
|
|||||||
|
|
||||||
return base * scale;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user