mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
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:
parent
df1813b4e2
commit
6e9392fb45
2 changed files with 108 additions and 46 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -335,6 +335,7 @@ namespace rsx
|
|||
u32 driver_handle;
|
||||
u32 result;
|
||||
u32 num_draws;
|
||||
u32 data_type;
|
||||
u64 sync_tag;
|
||||
u64 timestamp;
|
||||
bool pending;
|
||||
|
@ -367,8 +368,9 @@ namespace rsx
|
|||
sync_no_notify = 2 // If set, backend hint notifications will not be made
|
||||
};
|
||||
|
||||
struct ZCULL_control
|
||||
class ZCULL_control
|
||||
{
|
||||
protected:
|
||||
// Delay before a report update operation is forced to retire
|
||||
const u32 max_zcull_delay_us = 300;
|
||||
const u32 min_zcull_tick_us = 100;
|
||||
|
@ -377,8 +379,11 @@ namespace rsx
|
|||
const u32 occlusion_query_count = 1024;
|
||||
const u32 max_safe_queue_depth = 892;
|
||||
|
||||
bool active = false;
|
||||
bool enabled = false;
|
||||
bool unit_enabled = false; // The ZCULL unit is on
|
||||
bool write_enabled = false; // A surface in the ZCULL-monitored tile region has been loaded for rasterization
|
||||
bool stats_enabled = false; // Collecting of ZCULL statistics is enabled (not same as pixels passing Z test!)
|
||||
bool zpass_count_enabled = false; // Collecting of ZPASS statistics is enabled. If this is off, the counter does not increment
|
||||
bool host_queries_active = false; // The backend/host is gathering Z data for the ZCULL unit
|
||||
|
||||
std::array<occlusion_query_info, 1024> m_occlusion_query_data = {};
|
||||
std::stack<occlusion_query_info*> m_free_occlusion_pool;
|
||||
|
@ -397,17 +402,11 @@ namespace rsx
|
|||
std::vector<queued_report_write> m_pending_writes;
|
||||
std::unordered_map<u32, u32> m_statistics_map;
|
||||
|
||||
ZCULL_control();
|
||||
~ZCULL_control();
|
||||
// Enables/disables the ZCULL unit
|
||||
void set_active(class ::rsx::thread* ptimer, bool active, bool flush_queue);
|
||||
|
||||
void set_enabled(class ::rsx::thread* ptimer, bool state, bool flush_queue = false);
|
||||
void set_active(class ::rsx::thread* ptimer, bool state, bool flush_queue = false);
|
||||
|
||||
void write(vm::addr_t sink, u64 timestamp, u32 type, u32 value);
|
||||
void write(queued_report_write* writer, u64 timestamp, u32 value);
|
||||
|
||||
// Read current zcull statistics into the address provided
|
||||
void read_report(class ::rsx::thread* ptimer, vm::addr_t sink, u32 type);
|
||||
// Checks current state of the unit and applies changes
|
||||
void check_state(class ::rsx::thread* ptimer, bool flush_queue);
|
||||
|
||||
// Sets up a new query slot and sets it to the current task
|
||||
void allocate_new_query(class ::rsx::thread* ptimer);
|
||||
|
@ -415,6 +414,21 @@ namespace rsx
|
|||
// Free a query slot in use
|
||||
void free_query(occlusion_query_info* query);
|
||||
|
||||
// Write report to memory
|
||||
void write(vm::addr_t sink, u64 timestamp, u32 type, u32 value);
|
||||
void write(queued_report_write* writer, u64 timestamp, u32 value);
|
||||
|
||||
public:
|
||||
|
||||
ZCULL_control();
|
||||
~ZCULL_control();
|
||||
|
||||
void set_enabled(class ::rsx::thread* ptimer, bool state, bool flush_queue = false);
|
||||
void set_status(class ::rsx::thread* ptimer, bool surface_active, bool zpass_active, bool zcull_stats_active, bool flush_queue = false);
|
||||
|
||||
// Read current zcull statistics into the address provided
|
||||
void read_report(class ::rsx::thread* ptimer, vm::addr_t sink, u32 type);
|
||||
|
||||
// Clears current stat block and increments stat_tag_id
|
||||
void clear(class ::rsx::thread* ptimer);
|
||||
|
||||
|
@ -459,7 +473,7 @@ namespace rsx
|
|||
bool reserved = false;
|
||||
|
||||
std::vector<occlusion_query_info*> eval_sources;
|
||||
u32 eval_sync_tag = 0;
|
||||
u64 eval_sync_tag = 0;
|
||||
u32 eval_address = 0;
|
||||
|
||||
// Resets common data
|
||||
|
|
Loading…
Add table
Reference in a new issue