Skip to content

Commit

Permalink
vk: Latch query copy requests to reduce number of vulkan commands used
Browse files Browse the repository at this point in the history
  • Loading branch information
kd-11 committed Jun 16, 2023
1 parent 924692b commit 9709137
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
48 changes: 45 additions & 3 deletions rpcs3/Emu/RSX/VK/VKGSRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2894,7 +2894,7 @@ void VKGSRender::begin_conditional_rendering(const std::vector<rsx::reports::occ
if (!query_info.indices.empty())
{
const auto& index = query_info.indices.front();
m_occlusion_query_manager->get_query_result_indirect(*m_current_command_buffer, index, m_cond_render_buffer->value, 0);
m_occlusion_query_manager->get_query_result_indirect(*m_current_command_buffer, index, 1, m_cond_render_buffer->value, 0);

vk::insert_buffer_memory_barrier(*m_current_command_buffer, m_cond_render_buffer->value, 0, 4,
VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage,
Expand All @@ -2912,16 +2912,58 @@ void VKGSRender::begin_conditional_rendering(const std::vector<rsx::reports::occ
{
// We'll need to do some result aggregation using a compute shader.
auto scratch = vk::get_scratch_buffer(*m_current_command_buffer, num_hw_queries * 4);

// Range latching. Because of how the query pool manages allocations using a stack, we get an inverse sequential set of handles/indices that we can easily group together.
// This drastically boosts performance on some drivers like the NVIDIA proprietary one that seems to have a rather high cost for every individual query transer command.
std::pair<u32, u32> query_range = { umax, 0 };

auto copy_query_range_impl = [&]()
{
const auto count = (query_range.second - query_range.first + 1);
m_occlusion_query_manager->get_query_result_indirect(*m_current_command_buffer, query_range.first, count, scratch->value, dst_offset);
dst_offset += count * 4;
};

for (usz i = first; i < last; ++i)
{
auto& query_info = m_occlusion_map[sources[i]->driver_handle];
for (const auto& index : query_info.indices)
{
m_occlusion_query_manager->get_query_result_indirect(*m_current_command_buffer, index, scratch->value, dst_offset);
dst_offset += 4;
// First iteration?
if (query_range.first == umax)
{
query_range = { index, index };
continue;
}

// Head?
if ((query_range.first - 1) == index)
{
query_range.first = index;
continue;
}

// Tail?
if ((query_range.second + 1) == index)
{
query_range.second = index;
continue;
}

// Flush pending queue. In practice, this is never reached and we fall out to the spill block outside the loops
copy_query_range_impl();

// Start a new range for the current index
query_range = { index, index };
}
}

if (query_range.first != umax)
{
// Dangling queries, flush
copy_query_range_impl();
}

// Sanity check
ensure(dst_offset <= scratch->size());

Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/RSX/VK/VKQueryPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ namespace vk
return query_info.data;
}

void query_pool_manager::get_query_result_indirect(vk::command_buffer& cmd, u32 index, VkBuffer dst, VkDeviceSize dst_offset)
void query_pool_manager::get_query_result_indirect(vk::command_buffer& cmd, u32 index, u32 count, VkBuffer dst, VkDeviceSize dst_offset)
{
// We're technically supposed to stop any active renderpasses before streaming the results out, but that doesn't matter on IMR hw
// On TBDR setups like the apple M series, the stop is required (results are all 0 if you don't flush the RP), but this introduces a very heavy performance loss.
vkCmdCopyQueryPoolResults(cmd, *query_slot_status[index].pool, index, 1, dst, dst_offset, 4, VK_QUERY_RESULT_WAIT_BIT);
vkCmdCopyQueryPoolResults(cmd, *query_slot_status[index].pool, index, count, dst, dst_offset, 4, VK_QUERY_RESULT_WAIT_BIT);
}

void query_pool_manager::free_query(vk::command_buffer&/*cmd*/, u32 index)
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/VK/VKQueryPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace vk

bool check_query_status(u32 index);
u32 get_query_result(u32 index);
void get_query_result_indirect(vk::command_buffer& cmd, u32 index, VkBuffer dst, VkDeviceSize dst_offset);
void get_query_result_indirect(vk::command_buffer& cmd, u32 index, u32 count, VkBuffer dst, VkDeviceSize dst_offset);

u32 allocate_query(vk::command_buffer& cmd);
void free_query(vk::command_buffer&/*cmd*/, u32 index);
Expand Down

0 comments on commit 9709137

Please sign in to comment.