mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 06:00:12 +00:00
[TEST] Extend coalescing to more gpu to cpu regions
This commit is contained in:
@@ -791,6 +791,11 @@ bool BufferCache<P>::IsRegionGpuModified(DAddr addr, size_t size) {
|
|||||||
return is_dirty;
|
return is_dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
bool BufferCache<P>::IsRegionGpuModifiedCheap(DAddr addr, size_t size) {
|
||||||
|
return memory_tracker.IsRegionGpuModifiedCheap(addr, size);
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
bool BufferCache<P>::IsRegionRegistered(DAddr addr, size_t size) {
|
bool BufferCache<P>::IsRegionRegistered(DAddr addr, size_t size) {
|
||||||
const DAddr end_addr = addr + size;
|
const DAddr end_addr = addr + size;
|
||||||
@@ -1025,7 +1030,8 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||||||
}();
|
}();
|
||||||
const bool use_fast_buffer = needs_alignment_stream
|
const bool use_fast_buffer = needs_alignment_stream
|
||||||
|| (has_host_buffer && size <= channel_state->uniform_buffer_skip_cache_size
|
|| (has_host_buffer && size <= channel_state->uniform_buffer_skip_cache_size
|
||||||
&& !memory_tracker.IsRegionGpuModified(device_addr, size));
|
&& !(memory_tracker.IsRegionGpuModifiedCheap(device_addr, size)
|
||||||
|
&& memory_tracker.IsRegionGpuModified(device_addr, size)));
|
||||||
if (use_fast_buffer) {
|
if (use_fast_buffer) {
|
||||||
if constexpr (IS_OPENGL) {
|
if constexpr (IS_OPENGL) {
|
||||||
if (runtime.HasFastBufferSubData()) {
|
if (runtime.HasFastBufferSubData()) {
|
||||||
|
|||||||
@@ -300,6 +300,8 @@ public:
|
|||||||
/// Return true when a CPU region is modified from the GPU
|
/// Return true when a CPU region is modified from the GPU
|
||||||
[[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size);
|
[[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsRegionGpuModifiedCheap(DAddr addr, size_t size);
|
||||||
|
|
||||||
/// Return true when a region is registered on the cache
|
/// Return true when a region is registered on the cache
|
||||||
[[nodiscard]] bool IsRegionRegistered(DAddr addr, size_t size);
|
[[nodiscard]] bool IsRegionRegistered(DAddr addr, size_t size);
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,24 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsRegionGpuModifiedCheap(VAddr query_cpu_addr, u64 query_size) noexcept {
|
||||||
|
std::size_t remaining_size{query_size};
|
||||||
|
std::size_t page_index{query_cpu_addr >> HIGHER_PAGE_BITS};
|
||||||
|
u64 page_offset{query_cpu_addr & HIGHER_PAGE_MASK};
|
||||||
|
while (remaining_size > 0) {
|
||||||
|
const std::size_t copy_amount{
|
||||||
|
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
|
||||||
|
const Manager* manager = top_tier[page_index].load(std::memory_order_acquire);
|
||||||
|
if (manager != nullptr && manager->GpuModifiedPageCount() != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
page_index++;
|
||||||
|
page_offset = 0;
|
||||||
|
remaining_size -= copy_amount;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if a region has been modified from the CPU
|
/// Returns true if a region has been modified from the CPU
|
||||||
[[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
[[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
||||||
return IteratePages<true>(query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) {
|
return IteratePages<true>(query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ struct WordManager {
|
|||||||
[[maybe_unused]] std::span<u64> cached_words = Span(Type::CachedCPU);
|
[[maybe_unused]] std::span<u64> cached_words = Span(Type::CachedCPU);
|
||||||
std::vector<std::pair<VAddr, u64>> ranges;
|
std::vector<std::pair<VAddr, u64>> ranges;
|
||||||
s64 cpu_delta = 0;
|
s64 cpu_delta = 0;
|
||||||
|
s64 gpu_delta = 0;
|
||||||
IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) {
|
IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) {
|
||||||
if (type == Type::CPU || type == Type::CachedCPU) {
|
if (type == Type::CPU || type == Type::CachedCPU) {
|
||||||
CollectChangedRanges(!enable, index, untracked_words[index], mask, ranges);
|
CollectChangedRanges(!enable, index, untracked_words[index], mask, ranges);
|
||||||
@@ -134,6 +135,9 @@ struct WordManager {
|
|||||||
if (type == Type::CPU) {
|
if (type == Type::CPU) {
|
||||||
const u64 old = state_words[index];
|
const u64 old = state_words[index];
|
||||||
cpu_delta += enable ? std::popcount(~old & mask) : -std::popcount(old & mask);
|
cpu_delta += enable ? std::popcount(~old & mask) : -std::popcount(old & mask);
|
||||||
|
} else if (type == Type::GPU) {
|
||||||
|
const u64 old = state_words[index];
|
||||||
|
gpu_delta += enable ? std::popcount(~old & mask) : -std::popcount(old & mask);
|
||||||
}
|
}
|
||||||
if (enable) {
|
if (enable) {
|
||||||
state_words[index] |= mask;
|
state_words[index] |= mask;
|
||||||
@@ -152,6 +156,9 @@ struct WordManager {
|
|||||||
if (cpu_delta != 0) {
|
if (cpu_delta != 0) {
|
||||||
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
|
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
if (gpu_delta != 0) {
|
||||||
|
gpu_modified_pages.fetch_add(static_cast<u32>(gpu_delta), std::memory_order_release);
|
||||||
|
}
|
||||||
if (!ranges.empty()) {
|
if (!ranges.empty()) {
|
||||||
ApplyCollectedRanges(ranges, (!enable) ? 1 : -1);
|
ApplyCollectedRanges(ranges, (!enable) ? 1 : -1);
|
||||||
}
|
}
|
||||||
@@ -180,6 +187,7 @@ struct WordManager {
|
|||||||
};
|
};
|
||||||
std::vector<std::pair<VAddr, u64>> ranges;
|
std::vector<std::pair<VAddr, u64>> ranges;
|
||||||
s64 cpu_delta = 0;
|
s64 cpu_delta = 0;
|
||||||
|
s64 gpu_delta = 0;
|
||||||
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
||||||
if (type == Type::GPU)
|
if (type == Type::GPU)
|
||||||
mask &= ~untracked_words[index];
|
mask &= ~untracked_words[index];
|
||||||
@@ -190,6 +198,8 @@ struct WordManager {
|
|||||||
}
|
}
|
||||||
if (type == Type::CPU)
|
if (type == Type::CPU)
|
||||||
cpu_delta -= std::popcount(word);
|
cpu_delta -= std::popcount(word);
|
||||||
|
else if (type == Type::GPU)
|
||||||
|
gpu_delta -= std::popcount(word);
|
||||||
state_words[index] &= ~mask;
|
state_words[index] &= ~mask;
|
||||||
if (type == Type::CPU || type == Type::CachedCPU)
|
if (type == Type::CPU || type == Type::CachedCPU)
|
||||||
untracked_words[index] &= ~mask;
|
untracked_words[index] &= ~mask;
|
||||||
@@ -214,6 +224,9 @@ struct WordManager {
|
|||||||
if (cpu_delta != 0) {
|
if (cpu_delta != 0) {
|
||||||
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
|
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
if (gpu_delta != 0) {
|
||||||
|
gpu_modified_pages.fetch_add(static_cast<u32>(gpu_delta), std::memory_order_release);
|
||||||
|
}
|
||||||
if (pending) {
|
if (pending) {
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
@@ -348,10 +361,15 @@ struct WordManager {
|
|||||||
return cpu_modified_pages.load(std::memory_order_acquire);
|
return cpu_modified_pages.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u32 GpuModifiedPageCount() const noexcept {
|
||||||
|
return gpu_modified_pages.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
std::array<u64, size_t(Type::Max) * num_words> heap = {};
|
std::array<u64, size_t(Type::Max) * num_words> heap = {};
|
||||||
DeviceTracker* tracker = nullptr;
|
DeviceTracker* tracker = nullptr;
|
||||||
VAddr cpu_addr = 0;
|
VAddr cpu_addr = 0;
|
||||||
std::atomic<u32> cpu_modified_pages{0};
|
std::atomic<u32> cpu_modified_pages{0};
|
||||||
|
std::atomic<u32> gpu_modified_pages{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|||||||
@@ -684,9 +684,11 @@ void RasterizerVulkan::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType
|
|||||||
|
|
||||||
bool RasterizerVulkan::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
|
bool RasterizerVulkan::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
|
||||||
if ((True(which & VideoCommon::CacheType::BufferCache))) {
|
if ((True(which & VideoCommon::CacheType::BufferCache))) {
|
||||||
std::scoped_lock lock{buffer_cache.mutex};
|
if (buffer_cache.IsRegionGpuModifiedCheap(addr, size)) {
|
||||||
if (buffer_cache.IsRegionGpuModified(addr, size)) {
|
std::scoped_lock lock{buffer_cache.mutex};
|
||||||
return true;
|
if (buffer_cache.IsRegionGpuModified(addr, size)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Settings::IsGPULevelHigh()) {
|
if (!Settings::IsGPULevelHigh()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user