mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-26 12:42:41 +01:00
vulkan: Avoid cache miss whenever possible if WCB is enabled
This commit is contained in:
parent
a7c28f5827
commit
a24780fe5e
@ -1953,8 +1953,19 @@ void VKGSRender::prepare_rtts()
|
||||
(*m_device), &*m_current_command_buffer, m_optimal_tiling_supported_formats, m_memory_type_mapping);
|
||||
|
||||
//Reset framebuffer information
|
||||
VkFormat old_format = VK_FORMAT_UNDEFINED;
|
||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||
{
|
||||
//Flush old address if we keep missing it
|
||||
if (m_surface_info[i].pitch && g_cfg.video.write_color_buffers)
|
||||
{
|
||||
if (old_format == VK_FORMAT_UNDEFINED)
|
||||
old_format = vk::get_compatible_surface_format(m_surface_info[i].color_format).first;
|
||||
|
||||
m_texture_cache.flush_if_cache_miss_likely(old_format, m_surface_info[i].address, m_surface_info[i].pitch * m_surface_info[i].height,
|
||||
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
|
||||
}
|
||||
|
||||
m_surface_info[i].address = m_surface_info[i].pitch = 0;
|
||||
m_surface_info[i].width = clip_width;
|
||||
m_surface_info[i].height = clip_height;
|
||||
|
@ -118,6 +118,11 @@ namespace vk
|
||||
return managed_texture;
|
||||
}
|
||||
|
||||
VkFormat get_format()
|
||||
{
|
||||
return vram_texture->info.format;
|
||||
}
|
||||
|
||||
bool is_flushable() const
|
||||
{
|
||||
//This section is active and can be flushed to cpu
|
||||
@ -221,15 +226,19 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
void flush(vk::render_device& dev, vk::command_buffer& cmd, u32 heap_index, VkQueue submit_queue)
|
||||
bool flush(vk::render_device& dev, vk::command_buffer& cmd, u32 heap_index, VkQueue submit_queue)
|
||||
{
|
||||
if (m_device == nullptr)
|
||||
m_device = &dev;
|
||||
|
||||
// Return false if a flush occured 'late', i.e we had a miss
|
||||
bool result = true;
|
||||
|
||||
if (!synchronized)
|
||||
{
|
||||
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
|
||||
copy_texture(cmd, heap_index, submit_queue, true);
|
||||
result = false;
|
||||
}
|
||||
|
||||
protect(utils::protection::rw);
|
||||
@ -271,6 +280,8 @@ namespace vk
|
||||
|
||||
dma_buffer->unmap();
|
||||
//Its highly likely that this surface will be reused, so we just leave resources in place
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_synchronized() const
|
||||
@ -287,6 +298,16 @@ namespace vk
|
||||
std::vector<std::unique_ptr<vk::image_view> > m_temporary_image_view;
|
||||
std::vector<std::unique_ptr<vk::image>> m_dirty_textures;
|
||||
|
||||
// Keep track of cache misses to pre-emptively flush some addresses
|
||||
struct framebuffer_memory_characteristics
|
||||
{
|
||||
u32 misses;
|
||||
u32 block_size;
|
||||
VkFormat format;
|
||||
};
|
||||
|
||||
std::unordered_map<u32, framebuffer_memory_characteristics> m_cache_miss_statistics_table;
|
||||
|
||||
cached_texture_section& find_cached_texture(u32 rsx_address, u32 rsx_size, bool confirm_dimensions = false, u16 width = 0, u16 height = 0, u16 mipmaps = 0)
|
||||
{
|
||||
for (auto &tex : m_cache)
|
||||
@ -676,7 +697,13 @@ namespace vk
|
||||
}
|
||||
|
||||
//TODO: Map basic host_visible memory without coherent constraint
|
||||
tex.flush(dev, cmd, memory_types.host_visible_coherent, submit_queue);
|
||||
if (!tex.flush(dev, cmd, memory_types.host_visible_coherent, submit_queue))
|
||||
{
|
||||
//Missed address, note this
|
||||
//TODO: Lower severity when successful to keep the cache from overworking
|
||||
record_cache_miss(tex);
|
||||
}
|
||||
|
||||
response = true;
|
||||
}
|
||||
}
|
||||
@ -727,5 +754,59 @@ namespace vk
|
||||
m_dirty_textures.clear();
|
||||
m_temporary_image_view.clear();
|
||||
}
|
||||
|
||||
void record_cache_miss(cached_texture_section &tex)
|
||||
{
|
||||
const u32 memory_address = tex.get_section_base();
|
||||
const u32 memory_size = tex.get_section_size();
|
||||
const VkFormat fmt = tex.get_format();
|
||||
|
||||
auto It = m_cache_miss_statistics_table.find(memory_address);
|
||||
if (It == m_cache_miss_statistics_table.end())
|
||||
{
|
||||
m_cache_miss_statistics_table[memory_address] = { 1, memory_size, fmt };
|
||||
return;
|
||||
}
|
||||
|
||||
auto &value = It->second;
|
||||
if (value.format != fmt || value.block_size != memory_size)
|
||||
{
|
||||
m_cache_miss_statistics_table[memory_address] = { 1, memory_size, fmt };
|
||||
return;
|
||||
}
|
||||
|
||||
value.misses++;
|
||||
}
|
||||
|
||||
void flush_if_cache_miss_likely(const VkFormat fmt, const u32 memory_address, const u32 memory_size, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue)
|
||||
{
|
||||
auto It = m_cache_miss_statistics_table.find(memory_address);
|
||||
if (It == m_cache_miss_statistics_table.end())
|
||||
{
|
||||
m_cache_miss_statistics_table[memory_address] = { 0, memory_size, fmt };
|
||||
return;
|
||||
}
|
||||
|
||||
auto value = It->second;
|
||||
|
||||
if (value.format != fmt || value.block_size != memory_size)
|
||||
{
|
||||
//Reset since the data has changed
|
||||
//TODO: Keep track of all this information together
|
||||
m_cache_miss_statistics_table[memory_address] = { 0, memory_size, fmt };
|
||||
return;
|
||||
}
|
||||
|
||||
//Properly synchronized - no miss
|
||||
if (!value.misses) return;
|
||||
|
||||
//Auto flush if this address keeps missing (not properly synchronized)
|
||||
if (value.misses > 16)
|
||||
{
|
||||
//TODO: Determine better way of getting threshold
|
||||
LOG_ERROR(RSX, "Flushing memory at 0x%X -> Cache miss avoided", memory_address);
|
||||
flush_memory_to_cache(memory_address, memory_size, cmd, memory_types, submit_queue);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user