rsx: Restructure ZCULL query triggers

- Both ZCULL stats and ZPASS stats require hardware queries, but
  ZCULL stats should not contribute to ZPASS stats and vice versa!

- Disables hardware queries for ZCULL stats by themselves, we cannot
  generate them correctly anyway and no game so far has been found to
  actually use them. Should lessen the load on the backend for games
  that do not actually require it.
This commit is contained in:
kd-11 2020-02-22 18:19:16 +03:00 committed by kd-11
parent df1813b4e2
commit 6e9392fb45
2 changed files with 108 additions and 46 deletions

View file

@ -422,8 +422,7 @@ namespace rsx
element_push_buffer.clear();
if (zcull_ctrl->active)
zcull_ctrl->on_draw();
zcull_ctrl->on_draw();
if (capture_current_frame)
{
@ -2122,8 +2121,6 @@ namespace rsx
if (g_cfg.video.disable_zcull_queries)
return;
bool testing_enabled = zcull_pixel_cnt_enabled || zcull_stats_enabled;
if (framebuffer_swap)
{
zcull_surface_active = false;
@ -2148,7 +2145,7 @@ namespace rsx
}
zcull_ctrl->set_enabled(this, zcull_rendering_enabled);
zcull_ctrl->set_active(this, zcull_rendering_enabled && testing_enabled && zcull_surface_active);
zcull_ctrl->set_status(this, zcull_surface_active, zcull_pixel_cnt_enabled, zcull_stats_enabled);
}
void thread::clear_zcull_stats(u32 type)
@ -2564,12 +2561,6 @@ namespace rsx
Emu.Pause();
}
// Reset ZCULL ctrl
// NOTE: A semaphore release is part of RSX flip control and will handle ZCULL sync
// TODO: These routines belong in the state reset routines controlled by sys_rsx and cellGcmSetFlip
zcull_ctrl->set_active(this, false, true);
zcull_ctrl->clear(this);
// Save current state
m_queued_flip.stats = m_frame_stats;
m_queued_flip.push(buffer);
@ -2728,26 +2719,15 @@ namespace rsx
ZCULL_control::~ZCULL_control()
{}
void ZCULL_control::set_enabled(class ::rsx::thread* ptimer, bool state, bool flush_queue)
{
if (state != enabled)
{
enabled = state;
if (active && !enabled)
set_active(ptimer, false, flush_queue);
}
}
void ZCULL_control::set_active(class ::rsx::thread* ptimer, bool state, bool flush_queue)
{
if (state != active)
if (state != host_queries_active)
{
active = state;
host_queries_active = state;
if (state)
{
verify(HERE), enabled && m_current_task == nullptr;
verify(HERE), unit_enabled && m_current_task == nullptr;
allocate_new_query(ptimer);
begin_occlusion_query(m_current_task);
}
@ -2779,6 +2759,58 @@ namespace rsx
}
}
void ZCULL_control::check_state(class ::rsx::thread* ptimer, bool flush_queue)
{
// NOTE: Only enable host queries if pixel count is active to save on resources
// Can optionally be enabled for either stats enabled or zpass enabled for accuracy
const bool data_stream_available = write_enabled && (zpass_count_enabled /*|| stats_enabled*/);
if (host_queries_active && !data_stream_available)
{
// Stop
set_active(ptimer, false, flush_queue);
}
else if (!host_queries_active && data_stream_available && unit_enabled)
{
// Start
set_active(ptimer, true, flush_queue);
}
}
void ZCULL_control::set_enabled(class ::rsx::thread* ptimer, bool state, bool flush_queue)
{
if (state != unit_enabled)
{
unit_enabled = state;
check_state(ptimer, flush_queue);
}
}
void ZCULL_control::set_status(class ::rsx::thread* ptimer, bool surface_active, bool zpass_active, bool zcull_stats_active, bool flush_queue)
{
write_enabled = surface_active;
zpass_count_enabled = zpass_active;
stats_enabled = zcull_stats_active;
check_state(ptimer, flush_queue);
if (m_current_task && m_current_task->active)
{
// Data check
u32 expected_type = 0;
if (zpass_active) expected_type |= CELL_GCM_ZPASS_PIXEL_CNT;
if (zcull_stats_active) expected_type |= CELL_GCM_ZCULL_STATS;
if (m_current_task->data_type != expected_type) [[unlikely]]
{
rsx_log.error("ZCULL queue interrupted by data type change!");
// Stop+start the current setup
set_active(ptimer, false, false);
set_active(ptimer, true, false);
}
}
}
void ZCULL_control::read_report(::rsx::thread* ptimer, vm::addr_t sink, u32 type)
{
if (m_current_task && type == CELL_GCM_ZPASS_PIXEL_CNT)
@ -2855,12 +2887,18 @@ namespace rsx
m_current_task = m_free_occlusion_pool.top();
m_free_occlusion_pool.pop();
m_current_task->data_type = 0;
m_current_task->num_draws = 0;
m_current_task->result = 0;
m_current_task->active = true;
m_current_task->owned = false;
m_current_task->sync_tag = 0;
m_current_task->timestamp = 0;
// Flags determine what kind of payload is carried by queries in the 'report'
if (zpass_count_enabled) m_current_task->data_type |= CELL_GCM_ZPASS_PIXEL_CNT;
if (stats_enabled) m_current_task->data_type |= CELL_GCM_ZCULL_STATS;
return;
}
@ -2988,7 +3026,7 @@ namespace rsx
u32 processed = 0;
const bool has_unclaimed = (m_pending_writes.back().sink == 0);
//Write all claimed reports unconditionally
// Write all claimed reports unconditionally
for (auto &writer : m_pending_writes)
{
if (!writer.sink)
@ -3009,7 +3047,10 @@ namespace rsx
if (query->result)
{
result += query->result;
m_statistics_map[writer.counter_tag] = result;
if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT)
{
m_statistics_map[writer.counter_tag] += query->result;
}
}
}
else
@ -3024,7 +3065,8 @@ namespace rsx
if (!writer.forwarder)
{
// No other queries in the chain, write result
write(&writer, ptimer->timestamp(), result);
const auto value = (writer.type == CELL_GCM_ZPASS_PIXEL_CNT) ? m_statistics_map[writer.counter_tag] : result;
write(&writer, ptimer->timestamp(), value);
if (query && query->sync_tag == ptimer->cond_render_ctrl.eval_sync_tag)
{
@ -3171,7 +3213,10 @@ namespace rsx
if (query->result)
{
result += query->result;
m_statistics_map[writer.counter_tag] = result;
if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT)
{
m_statistics_map[writer.counter_tag] += query->result;
}
}
}
else
@ -3191,7 +3236,10 @@ namespace rsx
if (query->result)
{
result += query->result;
m_statistics_map[writer.counter_tag] = result;
if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT)
{
m_statistics_map[writer.counter_tag] += query->result;
}
}
}
else
@ -3212,11 +3260,11 @@ namespace rsx
stat_tag_to_remove = writer.counter_tag;
// only zpass supported right now
if (!writer.forwarder)
{
// No other queries in the chain, write result
write(&writer, ptimer->timestamp(), result);
const auto value = (writer.type == CELL_GCM_ZPASS_PIXEL_CNT) ? m_statistics_map[writer.counter_tag] : result;
write(&writer, ptimer->timestamp(), value);
if (query && query->sync_tag == ptimer->cond_render_ctrl.eval_sync_tag)
{