mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-30 02:32:46 +01:00
BufferCache: Additional download fixes.
This commit is contained in:
parent
f75544a943
commit
2c8f4ed27f
2 changed files with 107 additions and 23 deletions
|
@ -336,6 +336,7 @@ private:
|
||||||
std::vector<BufferId> cached_write_buffer_ids;
|
std::vector<BufferId> cached_write_buffer_ids;
|
||||||
|
|
||||||
IntervalSet uncommitted_ranges;
|
IntervalSet uncommitted_ranges;
|
||||||
|
IntervalSet common_ranges;
|
||||||
std::deque<IntervalSet> committed_ranges;
|
std::deque<IntervalSet> committed_ranges;
|
||||||
|
|
||||||
size_t immediate_buffer_capacity = 0;
|
size_t immediate_buffer_capacity = 0;
|
||||||
|
@ -359,6 +360,7 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
|
||||||
// Ensure the first slot is used for the null buffer
|
// Ensure the first slot is used for the null buffer
|
||||||
void(slot_buffers.insert(runtime, NullBufferParams{}));
|
void(slot_buffers.insert(runtime, NullBufferParams{}));
|
||||||
deletion_iterator = slot_buffers.end();
|
deletion_iterator = slot_buffers.end();
|
||||||
|
common_ranges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
@ -592,18 +594,55 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
|
||||||
const VAddr cpu_addr_end = interval.upper();
|
const VAddr cpu_addr_end = interval.upper();
|
||||||
ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) {
|
ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) {
|
||||||
boost::container::small_vector<BufferCopy, 1> copies;
|
boost::container::small_vector<BufferCopy, 1> copies;
|
||||||
buffer.ForEachDownloadRange(cpu_addr, size, true,
|
buffer.ForEachDownloadRange(
|
||||||
[&](u64 range_offset, u64 range_size) {
|
cpu_addr, size, true, [&](u64 range_offset, u64 range_size) {
|
||||||
|
const VAddr buffer_addr = buffer.CpuAddr();
|
||||||
|
const auto add_download = [&](VAddr start, VAddr end) {
|
||||||
|
const u64 new_offset = start - buffer_addr;
|
||||||
|
const u64 new_size = end - start;
|
||||||
downloads.push_back({
|
downloads.push_back({
|
||||||
BufferCopy{
|
BufferCopy{
|
||||||
.src_offset = range_offset,
|
.src_offset = new_offset,
|
||||||
.dst_offset = total_size_bytes,
|
.dst_offset = total_size_bytes,
|
||||||
.size = range_size,
|
.size = new_size,
|
||||||
},
|
},
|
||||||
buffer_id,
|
buffer_id,
|
||||||
});
|
});
|
||||||
total_size_bytes += range_size;
|
// Align up to avoid cache conflicts
|
||||||
largest_copy = std::max(largest_copy, range_size);
|
constexpr u64 align = 256ULL;
|
||||||
|
constexpr u64 mask = ~(align - 1ULL);
|
||||||
|
total_size_bytes += (new_size + align - 1) & mask;
|
||||||
|
largest_copy = std::max(largest_copy, new_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
const VAddr start_address = buffer_addr + range_offset;
|
||||||
|
const VAddr end_address = start_address + range_size;
|
||||||
|
const IntervalType search_interval{cpu_addr, 1};
|
||||||
|
auto it = common_ranges.lower_bound(search_interval);
|
||||||
|
if (it == common_ranges.end()) {
|
||||||
|
it = common_ranges.begin();
|
||||||
|
}
|
||||||
|
while (it != common_ranges.end()) {
|
||||||
|
VAddr inter_addr_end = it->upper();
|
||||||
|
VAddr inter_addr = it->lower();
|
||||||
|
if (inter_addr >= end_address) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inter_addr_end <= start_address) {
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inter_addr_end > end_address) {
|
||||||
|
inter_addr_end = end_address;
|
||||||
|
}
|
||||||
|
if (inter_addr < start_address) {
|
||||||
|
inter_addr = start_address;
|
||||||
|
}
|
||||||
|
add_download(inter_addr, inter_addr_end);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
const IntervalType subtract_interval{start_address, end_address};
|
||||||
|
common_ranges.subtract(subtract_interval);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1060,13 +1099,15 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 s
|
||||||
Buffer& buffer = slot_buffers[buffer_id];
|
Buffer& buffer = slot_buffers[buffer_id];
|
||||||
buffer.MarkRegionAsGpuModified(cpu_addr, size);
|
buffer.MarkRegionAsGpuModified(cpu_addr, size);
|
||||||
|
|
||||||
|
const IntervalType base_interval{cpu_addr, cpu_addr + size};
|
||||||
|
common_ranges.add(base_interval);
|
||||||
|
|
||||||
const bool is_accuracy_high =
|
const bool is_accuracy_high =
|
||||||
Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High;
|
Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High;
|
||||||
const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
|
const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
|
||||||
if (!is_async && !is_accuracy_high) {
|
if (!is_async && !is_accuracy_high) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const IntervalType base_interval{cpu_addr, cpu_addr + size};
|
|
||||||
uncommitted_ranges.add(base_interval);
|
uncommitted_ranges.add(base_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,13 +1333,50 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
|
||||||
u64 total_size_bytes = 0;
|
u64 total_size_bytes = 0;
|
||||||
u64 largest_copy = 0;
|
u64 largest_copy = 0;
|
||||||
buffer.ForEachDownloadRange(cpu_addr, size, true, [&](u64 range_offset, u64 range_size) {
|
buffer.ForEachDownloadRange(cpu_addr, size, true, [&](u64 range_offset, u64 range_size) {
|
||||||
|
const VAddr buffer_addr = buffer.CpuAddr();
|
||||||
|
const auto add_download = [&](VAddr start, VAddr end) {
|
||||||
|
const u64 new_offset = start - buffer_addr;
|
||||||
|
const u64 new_size = end - start;
|
||||||
copies.push_back(BufferCopy{
|
copies.push_back(BufferCopy{
|
||||||
.src_offset = range_offset,
|
.src_offset = new_offset,
|
||||||
.dst_offset = total_size_bytes,
|
.dst_offset = total_size_bytes,
|
||||||
.size = range_size,
|
.size = new_size,
|
||||||
});
|
});
|
||||||
total_size_bytes += range_size;
|
// Align up to avoid cache conflicts
|
||||||
largest_copy = std::max(largest_copy, range_size);
|
constexpr u64 align = 256ULL;
|
||||||
|
constexpr u64 mask = ~(align - 1ULL);
|
||||||
|
total_size_bytes += (new_size + align - 1) & mask;
|
||||||
|
largest_copy = std::max(largest_copy, new_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
const VAddr start_address = buffer_addr + range_offset;
|
||||||
|
const VAddr end_address = start_address + range_size;
|
||||||
|
const IntervalType search_interval{start_address - range_size, 1};
|
||||||
|
auto it = common_ranges.lower_bound(search_interval);
|
||||||
|
if (it == common_ranges.end()) {
|
||||||
|
it = common_ranges.begin();
|
||||||
|
}
|
||||||
|
while (it != common_ranges.end()) {
|
||||||
|
VAddr inter_addr_end = it->upper();
|
||||||
|
VAddr inter_addr = it->lower();
|
||||||
|
if (inter_addr >= end_address) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inter_addr_end <= start_address) {
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inter_addr_end > end_address) {
|
||||||
|
inter_addr_end = end_address;
|
||||||
|
}
|
||||||
|
if (inter_addr < start_address) {
|
||||||
|
inter_addr = start_address;
|
||||||
|
}
|
||||||
|
add_download(inter_addr, inter_addr_end);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
const IntervalType subtract_interval{start_address, end_address};
|
||||||
|
common_ranges.subtract(subtract_interval);
|
||||||
});
|
});
|
||||||
if (total_size_bytes == 0) {
|
if (total_size_bytes == 0) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "common/cityhash.h"
|
#include "common/cityhash.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/dma_pusher.h"
|
#include "video_core/dma_pusher.h"
|
||||||
|
@ -76,9 +77,14 @@ bool DmaPusher::Step() {
|
||||||
|
|
||||||
// Push buffer non-empty, read a word
|
// Push buffer non-empty, read a word
|
||||||
command_headers.resize(command_list_header.size);
|
command_headers.resize(command_list_header.size);
|
||||||
|
if (Settings::IsGPULevelHigh()) {
|
||||||
|
gpu.MemoryManager().ReadBlock(dma_get, command_headers.data(),
|
||||||
|
command_list_header.size * sizeof(u32));
|
||||||
|
} else {
|
||||||
gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(),
|
gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(),
|
||||||
command_list_header.size * sizeof(u32));
|
command_list_header.size * sizeof(u32));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (std::size_t index = 0; index < command_headers.size();) {
|
for (std::size_t index = 0; index < command_headers.size();) {
|
||||||
const CommandHeader& command_header = command_headers[index];
|
const CommandHeader& command_header = command_headers[index];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue