mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
vk: Refactoring and optimizations to query handling
- Caches query results when looking up report availability to avoid entering driver code twice. - Minor code restructuring
This commit is contained in:
parent
55ad9244c0
commit
9f94a6dc11
2 changed files with 92 additions and 68 deletions
|
@ -2224,52 +2224,43 @@ void VKGSRender::sync_hint(rsx::FIFO_hint hint, void* args)
|
|||
verify(HERE), args;
|
||||
rsx::thread::sync_hint(hint, args);
|
||||
|
||||
// Occlusion queries not enabled, do nothing
|
||||
if (!(m_current_command_buffer->flags & vk::command_buffer::cb_has_occlusion_task))
|
||||
return;
|
||||
|
||||
// Check if the required report is synced to this CB
|
||||
auto occlusion_info = static_cast<rsx::reports::occlusion_query_info*>(args);
|
||||
auto& data = m_occlusion_map[occlusion_info->driver_handle];
|
||||
|
||||
if (data.command_buffer_to_wait != m_current_command_buffer || data.indices.empty())
|
||||
return;
|
||||
|
||||
// Occlusion test result evaluation is coming up, avoid a hard sync
|
||||
switch (hint)
|
||||
{
|
||||
case rsx::FIFO_hint::hint_conditional_render_eval:
|
||||
{
|
||||
// Occlusion queries not enabled, do nothing
|
||||
if (!(m_current_command_buffer->flags & vk::command_buffer::cb_has_occlusion_task))
|
||||
return;
|
||||
|
||||
// If a flush request is already enqueued, do nothing
|
||||
if (m_flush_requests.pending())
|
||||
return;
|
||||
|
||||
// Check if the required report is synced to this CB
|
||||
auto occlusion_info = static_cast<rsx::reports::occlusion_query_info*>(args);
|
||||
auto& data = m_occlusion_map[occlusion_info->driver_handle];
|
||||
|
||||
if (data.command_buffer_to_wait == m_current_command_buffer && !data.indices.empty())
|
||||
{
|
||||
// Confirmed hard sync coming up, post a sync request
|
||||
m_flush_requests.post(false);
|
||||
m_flush_requests.remove_one();
|
||||
}
|
||||
|
||||
// Schedule a sync on the next loop iteration
|
||||
m_flush_requests.post(false);
|
||||
m_flush_requests.remove_one();
|
||||
break;
|
||||
}
|
||||
case rsx::FIFO_hint::hint_zcull_sync:
|
||||
{
|
||||
if (!(m_current_command_buffer->flags & vk::command_buffer::cb_has_occlusion_task))
|
||||
return;
|
||||
// Unavoidable hard sync coming up, flush immediately
|
||||
// This heavyweight hint should be used with caution
|
||||
std::lock_guard lock(m_flush_queue_mutex);
|
||||
flush_command_queue();
|
||||
|
||||
auto occlusion_info = static_cast<rsx::reports::occlusion_query_info*>(args);
|
||||
auto& data = m_occlusion_map[occlusion_info->driver_handle];
|
||||
|
||||
if (data.command_buffer_to_wait == m_current_command_buffer && !data.indices.empty())
|
||||
if (m_flush_requests.pending())
|
||||
{
|
||||
std::lock_guard lock(m_flush_queue_mutex);
|
||||
flush_command_queue();
|
||||
|
||||
if (m_flush_requests.pending())
|
||||
{
|
||||
// Clear without wait
|
||||
m_flush_requests.clear_pending_flag();
|
||||
}
|
||||
// Clear without wait
|
||||
m_flush_requests.clear_pending_flag();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2991,11 +2991,62 @@ public:
|
|||
|
||||
class occlusion_query_pool
|
||||
{
|
||||
struct query_slot_info
|
||||
{
|
||||
bool any_passed;
|
||||
bool active;
|
||||
bool ready;
|
||||
};
|
||||
|
||||
VkQueryPool query_pool = VK_NULL_HANDLE;
|
||||
vk::render_device* owner = nullptr;
|
||||
|
||||
std::deque<u32> available_slots;
|
||||
std::vector<bool> query_active_status;
|
||||
std::vector<query_slot_info> query_slot_status;
|
||||
|
||||
inline bool poke_query(query_slot_info& query, u32 index)
|
||||
{
|
||||
// Query is ready if:
|
||||
// 1. Any sample has been determined to have passed the Z test
|
||||
// 2. The backend has fully processed the query and found no hits
|
||||
|
||||
u32 result[2] = { 0, 0 };
|
||||
switch (const auto error = vkGetQueryPoolResults(*owner, query_pool, index, 1, 8, result, 8, VK_QUERY_RESULT_PARTIAL_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT))
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
{
|
||||
if (result[0])
|
||||
{
|
||||
query.any_passed = true;
|
||||
query.ready = true;
|
||||
return true;
|
||||
}
|
||||
else if (result[1])
|
||||
{
|
||||
query.any_passed = false;
|
||||
query.ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
case VK_NOT_READY:
|
||||
{
|
||||
if (result[0])
|
||||
{
|
||||
query.any_passed = true;
|
||||
query.ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
die_with_error(HERE, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void create(vk::render_device &dev, u32 num_entries)
|
||||
|
@ -3009,7 +3060,7 @@ public:
|
|||
owner = &dev;
|
||||
|
||||
// From spec: "After query pool creation, each query must be reset before it is used."
|
||||
query_active_status.resize(num_entries, true);
|
||||
query_slot_status.resize(num_entries, {});
|
||||
}
|
||||
|
||||
void destroy()
|
||||
|
@ -3025,10 +3076,11 @@ public:
|
|||
|
||||
void initialize(vk::command_buffer &cmd)
|
||||
{
|
||||
const u32 count = ::size32(query_active_status);
|
||||
const u32 count = ::size32(query_slot_status);
|
||||
vkCmdResetQueryPool(cmd, query_pool, 0, count);
|
||||
|
||||
std::fill(query_active_status.begin(), query_active_status.end(), false);
|
||||
query_slot_info value{};
|
||||
std::fill(query_slot_status.begin(), query_slot_status.end(), value);
|
||||
|
||||
for (u32 n = 0; n < count; ++n)
|
||||
{
|
||||
|
@ -3038,14 +3090,15 @@ public:
|
|||
|
||||
void begin_query(vk::command_buffer &cmd, u32 index)
|
||||
{
|
||||
if (query_active_status[index])
|
||||
if (query_slot_status[index].active)
|
||||
{
|
||||
//Synchronization must be done externally
|
||||
vkCmdResetQueryPool(cmd, query_pool, index, 1);
|
||||
query_slot_status[index] = {};
|
||||
}
|
||||
|
||||
vkCmdBeginQuery(cmd, query_pool, index, 0);//VK_QUERY_CONTROL_PRECISE_BIT);
|
||||
query_active_status[index] = true;
|
||||
query_slot_status[index].active = true;
|
||||
}
|
||||
|
||||
void end_query(vk::command_buffer &cmd, u32 index)
|
||||
|
@ -3055,40 +3108,20 @@ public:
|
|||
|
||||
bool check_query_status(u32 index)
|
||||
{
|
||||
u32 result[2] = {0, 0};
|
||||
switch (const auto error = vkGetQueryPoolResults(*owner, query_pool, index, 1, 8, result, 8, VK_QUERY_RESULT_PARTIAL_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT))
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return (result[0] || result[1]);
|
||||
case VK_NOT_READY:
|
||||
return false;
|
||||
default:
|
||||
die_with_error(HERE, error);
|
||||
return false;
|
||||
}
|
||||
return poke_query(query_slot_status[index], index);
|
||||
}
|
||||
|
||||
u32 get_query_result(u32 index)
|
||||
{
|
||||
u32 result[2] = { 0, 0 };
|
||||
// Check for cached result
|
||||
auto& query_info = query_slot_status[index];
|
||||
|
||||
do
|
||||
while (!query_info.ready)
|
||||
{
|
||||
switch (const auto error = vkGetQueryPoolResults(*owner, query_pool, index, 1, 8, result, 8, VK_QUERY_RESULT_PARTIAL_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT))
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
if (result[0]) return 1u;
|
||||
if (result[1]) return 0u; // Partial result can return SUCCESS when unavailable
|
||||
continue;
|
||||
case VK_NOT_READY:
|
||||
if (result[0]) return 1u; // Partial result can return NOT_READY when unavailable
|
||||
continue;
|
||||
default:
|
||||
die_with_error(HERE, error);
|
||||
return false;
|
||||
}
|
||||
poke_query(query_info, index);
|
||||
}
|
||||
while (true);
|
||||
|
||||
return query_info.any_passed ? 1 : 0;
|
||||
}
|
||||
|
||||
void get_query_result_indirect(vk::command_buffer &cmd, u32 index, VkBuffer dst, VkDeviceSize dst_offset)
|
||||
|
@ -3098,11 +3131,11 @@ public:
|
|||
|
||||
void reset_query(vk::command_buffer &cmd, u32 index)
|
||||
{
|
||||
if (query_active_status[index])
|
||||
if (query_slot_status[index].active)
|
||||
{
|
||||
vkCmdResetQueryPool(cmd, query_pool, index, 1);
|
||||
|
||||
query_active_status[index] = false;
|
||||
query_slot_status[index] = {};
|
||||
available_slots.push_back(index);
|
||||
}
|
||||
}
|
||||
|
@ -3116,9 +3149,9 @@ public:
|
|||
|
||||
void reset_all(vk::command_buffer &cmd)
|
||||
{
|
||||
for (u32 n = 0; n < query_active_status.size(); n++)
|
||||
for (u32 n = 0; n < query_slot_status.size(); n++)
|
||||
{
|
||||
if (query_active_status[n])
|
||||
if (query_slot_status[n].active)
|
||||
reset_query(cmd, n);
|
||||
}
|
||||
}
|
||||
|
@ -3133,7 +3166,7 @@ public:
|
|||
u32 result = available_slots.front();
|
||||
available_slots.pop_front();
|
||||
|
||||
verify(HERE), !query_active_status[result];
|
||||
verify(HERE), !query_slot_status[result].active;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue