diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 6e90c3c406..ed0e6a67f5 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3262,6 +3262,35 @@ namespace rsx } } + void ZCULL_control::retire(::rsx::thread* ptimer, queued_report_write* writer, u32 result) + { + if (!writer->forwarder) + { + // No other queries in the chain, write result + const auto value = (writer->type == CELL_GCM_ZPASS_PIXEL_CNT) ? m_statistics_map[writer->counter_tag] : result; + write(writer, ptimer->timestamp(), value); + } + + if (writer->query && writer->query->sync_tag == ptimer->cond_render_ctrl.eval_sync_tag) + { + bool eval_failed; + if (!writer->forwarder) [[likely]] + { + // Normal evaluation + eval_failed = (result == 0u); + } + else + { + // Eval was inserted while ZCULL was active but not enqueued to write to memory yet + // write(addr) -> enable_zpass_stats -> eval_condition -> write(addr) + // In this case, use what already exists in memory, not the current counter + eval_failed = (vm::_ref(writer->sink).value == 0u); + } + + ptimer->cond_render_ctrl.set_eval_result(ptimer, eval_failed); + } + } + void ZCULL_control::sync(::rsx::thread* ptimer) { if (!m_pending_writes.empty()) @@ -3320,19 +3349,7 @@ namespace rsx free_query(query); } - if (!writer.forwarder) - { - // No other queries in the chain, write 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) - { - const bool eval_failed = (result == 0); - ptimer->cond_render_ctrl.set_eval_result(ptimer, eval_failed); - } - } - + retire(ptimer, &writer, result); processed++; } @@ -3451,7 +3468,7 @@ namespace rsx u32 result = m_statistics_map[writer.counter_tag]; const bool force_read = (sync_address != 0); - if (force_read && writer.sink == sync_address) + if (force_read && writer.sink == sync_address && !writer.forwarder) { // Forced reads end here sync_address = 0; @@ -3518,19 +3535,7 @@ namespace rsx stat_tag_to_remove = writer.counter_tag; - if (!writer.forwarder) - { - // No other queries in the chain, write 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) - { - const bool eval_failed = (result == 0); - ptimer->cond_render_ctrl.set_eval_result(ptimer, eval_failed); - } - } - + retire(ptimer, &writer, result); processed++; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index b9452e79d9..853e1c72d0 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -437,6 +437,9 @@ namespace rsx void write(vm::addr_t sink, u64 timestamp, u32 type, u32 value); void write(queued_report_write* writer, u64 timestamp, u32 value); + // Retire operation + void retire(class ::rsx::thread* ptimer, queued_report_write* writer, u32 result); + public: ZCULL_control();