Query Cache: Fix guest side sample counting

This commit is contained in:
Fernando Sahmkow
2023-08-19 21:49:38 +02:00
parent 282ae8fa51
commit 2fea1b8407
5 changed files with 97 additions and 46 deletions

View File

@ -9,16 +9,15 @@
namespace VideoCommon {
enum class QueryFlagBits : u32 {
HasTimestamp = 1 << 0, ///< Indicates if this query has a timestamp.
IsFinalValueSynced = 1 << 1, ///< Indicates if the query has been synced in the host
IsHostSynced = 1 << 2, ///< Indicates if the query has been synced in the host
IsGuestSynced = 1 << 3, ///< Indicates if the query has been synced with the guest.
IsHostManaged = 1 << 4, ///< Indicates if this query points to a host query
IsRewritten = 1 << 5, ///< Indicates if this query was rewritten by another query
IsInvalidated = 1 << 6, ///< Indicates the value of th query has been nullified.
IsOrphan = 1 << 7, ///< Indicates the query has not been set by a guest query.
IsFence = 1 << 8, ///< Indicates the query is a fence.
IsQueuedForAsyncFlush = 1 << 9, ///< Indicates that the query can be flushed at any moment
HasTimestamp = 1 << 0, ///< Indicates if this query has a timestamp.
IsFinalValueSynced = 1 << 1, ///< Indicates if the query has been synced in the host
IsHostSynced = 1 << 2, ///< Indicates if the query has been synced in the host
IsGuestSynced = 1 << 3, ///< Indicates if the query has been synced with the guest.
IsHostManaged = 1 << 4, ///< Indicates if this query points to a host query
IsRewritten = 1 << 5, ///< Indicates if this query was rewritten by another query
IsInvalidated = 1 << 6, ///< Indicates the value of th query has been nullified.
IsOrphan = 1 << 7, ///< Indicates the query has not been set by a guest query.
IsFence = 1 << 8, ///< Indicates the query is a fence.
};
DECLARE_ENUM_FLAG_OPERATORS(QueryFlagBits)

View File

@ -256,30 +256,32 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
u8* pointer = impl->cpu_memory.GetPointer(cpu_addr);
u8* pointer_timestamp = impl->cpu_memory.GetPointer(cpu_addr + 8);
bool is_synced = !Settings::IsGPULevelHigh() && is_fence;
std::function<void()> operation(
[this, is_synced, query_base = query, query_location, pointer, pointer_timestamp] {
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
}
return;
}
if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
UNREACHABLE();
return;
}
if (True(query_base->flags & QueryFlagBits::HasTimestamp)) {
u64 timestamp = impl->gpu.GetTicks();
std::memcpy(pointer_timestamp, &timestamp, sizeof(timestamp));
std::memcpy(pointer, &query_base->value, sizeof(query_base->value));
} else {
u32 value = static_cast<u32>(query_base->value);
std::memcpy(pointer, &value, sizeof(value));
}
std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
pointer, pointer_timestamp] {
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
}
});
return;
}
if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
UNREACHABLE();
return;
}
query_base->value += streamer->GetAmmendValue();
streamer->SetAccumulationValue(query_base->value);
if (True(query_base->flags & QueryFlagBits::HasTimestamp)) {
u64 timestamp = impl->gpu.GetTicks();
std::memcpy(pointer_timestamp, &timestamp, sizeof(timestamp));
std::memcpy(pointer, &query_base->value, sizeof(query_base->value));
} else {
u32 value = static_cast<u32>(query_base->value);
std::memcpy(pointer, &value, sizeof(value));
}
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
}
});
if (is_fence) {
impl->rasterizer.SignalFence(std::move(operation));
} else {
@ -354,9 +356,9 @@ void QueryCacheBase<Traits>::NotifySegment(bool resume) {
if (resume) {
impl->runtime.ResumeHostConditionalRendering();
} else {
impl->runtime.PauseHostConditionalRendering();
CounterClose(VideoCommon::QueryType::ZPassPixelCount64);
CounterClose(VideoCommon::QueryType::StreamingByteCount);
impl->runtime.PauseHostConditionalRendering();
}
}

View File

@ -78,6 +78,14 @@ public:
return dependence_mask;
}
u64 GetAmmendValue() const {
return ammend_value;
}
void SetAccumulationValue(u64 new_value) {
acumulation_value = new_value;
}
protected:
void MakeDependent(StreamerInterface* depend_on) {
dependence_mask |= 1ULL << depend_on->id;
@ -87,6 +95,8 @@ protected:
const size_t id;
u64 dependence_mask;
u64 dependent_mask;
u64 ammend_value{};
u64 acumulation_value{};
};
template <typename QueryType>