|
|
@ -152,6 +152,8 @@ public: |
|
|
/// Return true when there are uncommitted buffers to be downloaded |
|
|
/// Return true when there are uncommitted buffers to be downloaded |
|
|
[[nodiscard]] bool HasUncommittedFlushes() const noexcept; |
|
|
[[nodiscard]] bool HasUncommittedFlushes() const noexcept; |
|
|
|
|
|
|
|
|
|
|
|
void AccumulateFlushes(); |
|
|
|
|
|
|
|
|
/// Return true when the caller should wait for async downloads |
|
|
/// Return true when the caller should wait for async downloads |
|
|
[[nodiscard]] bool ShouldWaitAsyncFlushes() const noexcept; |
|
|
[[nodiscard]] bool ShouldWaitAsyncFlushes() const noexcept; |
|
|
|
|
|
|
|
|
@ -334,6 +336,7 @@ private: |
|
|
std::vector<BufferId> cached_write_buffer_ids; |
|
|
std::vector<BufferId> cached_write_buffer_ids; |
|
|
|
|
|
|
|
|
IntervalSet uncommitted_ranges; |
|
|
IntervalSet uncommitted_ranges; |
|
|
|
|
|
std::deque<IntervalSet> committed_ranges; |
|
|
|
|
|
|
|
|
size_t immediate_buffer_capacity = 0; |
|
|
size_t immediate_buffer_capacity = 0; |
|
|
std::unique_ptr<u8[]> immediate_buffer_alloc; |
|
|
std::unique_ptr<u8[]> immediate_buffer_alloc; |
|
|
@ -551,7 +554,19 @@ void BufferCache<P>::FlushCachedWrites() { |
|
|
|
|
|
|
|
|
template <class P> |
|
|
template <class P> |
|
|
bool BufferCache<P>::HasUncommittedFlushes() const noexcept { |
|
|
bool BufferCache<P>::HasUncommittedFlushes() const noexcept { |
|
|
return !uncommitted_ranges.empty(); |
|
|
|
|
|
|
|
|
return !uncommitted_ranges.empty() || !committed_ranges.empty(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <class P> |
|
|
|
|
|
void BufferCache<P>::AccumulateFlushes() { |
|
|
|
|
|
if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { |
|
|
|
|
|
uncommitted_ranges.clear(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (uncommitted_ranges.empty()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
committed_ranges.emplace_back(std::move(uncommitted_ranges)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class P> |
|
|
template <class P> |
|
|
@ -561,8 +576,8 @@ bool BufferCache<P>::ShouldWaitAsyncFlushes() const noexcept { |
|
|
|
|
|
|
|
|
template <class P> |
|
|
template <class P> |
|
|
void BufferCache<P>::CommitAsyncFlushesHigh() { |
|
|
void BufferCache<P>::CommitAsyncFlushesHigh() { |
|
|
const IntervalSet& intervals = uncommitted_ranges; |
|
|
|
|
|
if (intervals.empty()) { |
|
|
|
|
|
|
|
|
AccumulateFlushes(); |
|
|
|
|
|
if (committed_ranges.empty()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
MICROPROFILE_SCOPE(GPU_DownloadMemory); |
|
|
MICROPROFILE_SCOPE(GPU_DownloadMemory); |
|
|
@ -570,6 +585,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { |
|
|
boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads; |
|
|
boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads; |
|
|
u64 total_size_bytes = 0; |
|
|
u64 total_size_bytes = 0; |
|
|
u64 largest_copy = 0; |
|
|
u64 largest_copy = 0; |
|
|
|
|
|
for (const IntervalSet& intervals : committed_ranges) { |
|
|
for (auto& interval : intervals) { |
|
|
for (auto& interval : intervals) { |
|
|
const std::size_t size = interval.upper() - interval.lower(); |
|
|
const std::size_t size = interval.upper() - interval.lower(); |
|
|
const VAddr cpu_addr = interval.lower(); |
|
|
const VAddr cpu_addr = interval.lower(); |
|
|
@ -607,6 +623,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
committed_ranges.clear(); |
|
|
if (downloads.empty()) { |
|
|
if (downloads.empty()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
@ -644,6 +662,7 @@ void BufferCache<P>::CommitAsyncFlushes() { |
|
|
CommitAsyncFlushesHigh(); |
|
|
CommitAsyncFlushesHigh(); |
|
|
} else { |
|
|
} else { |
|
|
uncommitted_ranges.clear(); |
|
|
uncommitted_ranges.clear(); |
|
|
|
|
|
committed_ranges.clear(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|