|
@@ -71,6 +71,12 @@ class BufferCache {
|
|
|
|
|
|
|
|
struct Empty {};
|
|
struct Empty {};
|
|
|
|
|
|
|
|
|
|
+ struct OverlapResult {
|
|
|
|
|
+ std::vector<BufferId> ids;
|
|
|
|
|
+ VAddr begin;
|
|
|
|
|
+ VAddr end;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
struct Binding {
|
|
struct Binding {
|
|
|
VAddr cpu_addr{};
|
|
VAddr cpu_addr{};
|
|
|
u32 size{};
|
|
u32 size{};
|
|
@@ -220,6 +226,10 @@ private:
|
|
|
|
|
|
|
|
[[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
|
|
[[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
|
|
|
|
|
|
|
|
|
|
+ [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size);
|
|
|
|
|
+
|
|
|
|
|
+ void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id);
|
|
|
|
|
+
|
|
|
[[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size);
|
|
[[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size);
|
|
|
|
|
|
|
|
void Register(BufferId buffer_id);
|
|
void Register(BufferId buffer_id);
|
|
@@ -988,12 +998,12 @@ BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template <class P>
|
|
template <class P>
|
|
|
-BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
|
|
|
|
|
|
|
+typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr,
|
|
|
|
|
+ u32 wanted_size) {
|
|
|
std::vector<BufferId> overlap_ids;
|
|
std::vector<BufferId> overlap_ids;
|
|
|
- VAddr cpu_addr_begin = cpu_addr;
|
|
|
|
|
- VAddr cpu_addr_end = cpu_addr + wanted_size;
|
|
|
|
|
- for (; cpu_addr >> PAGE_BITS < Common::DivCeil(cpu_addr_end, PAGE_SIZE);
|
|
|
|
|
- cpu_addr += PAGE_SIZE) {
|
|
|
|
|
|
|
+ VAddr begin = cpu_addr;
|
|
|
|
|
+ VAddr end = cpu_addr + wanted_size;
|
|
|
|
|
+ for (; cpu_addr >> PAGE_BITS < Common::DivCeil(end, PAGE_SIZE); cpu_addr += PAGE_SIZE) {
|
|
|
const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS];
|
|
const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS];
|
|
|
if (!overlap_id) {
|
|
if (!overlap_id) {
|
|
|
continue;
|
|
continue;
|
|
@@ -1005,35 +1015,48 @@ BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
|
|
|
overlap.Pick();
|
|
overlap.Pick();
|
|
|
overlap_ids.push_back(overlap_id);
|
|
overlap_ids.push_back(overlap_id);
|
|
|
const VAddr overlap_cpu_addr = overlap.CpuAddr();
|
|
const VAddr overlap_cpu_addr = overlap.CpuAddr();
|
|
|
- if (overlap_cpu_addr < cpu_addr_begin) {
|
|
|
|
|
- cpu_addr = cpu_addr_begin = overlap_cpu_addr;
|
|
|
|
|
|
|
+ if (overlap_cpu_addr < begin) {
|
|
|
|
|
+ cpu_addr = begin = overlap_cpu_addr;
|
|
|
}
|
|
}
|
|
|
- cpu_addr_end = std::max(cpu_addr_end, overlap_cpu_addr + overlap.SizeBytes());
|
|
|
|
|
|
|
+ end = std::max(end, overlap_cpu_addr + overlap.SizeBytes());
|
|
|
}
|
|
}
|
|
|
- const u32 size = static_cast<u32>(cpu_addr_end - cpu_addr_begin);
|
|
|
|
|
- const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, cpu_addr_begin, size);
|
|
|
|
|
- Buffer& new_buffer = slot_buffers[new_buffer_id];
|
|
|
|
|
|
|
+ return OverlapResult{
|
|
|
|
|
+ .ids = std::move(overlap_ids),
|
|
|
|
|
+ .begin = begin,
|
|
|
|
|
+ .end = end,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- for (const BufferId overlap_id : overlap_ids) {
|
|
|
|
|
- Buffer& overlap = slot_buffers[overlap_id];
|
|
|
|
|
- overlap.Unpick();
|
|
|
|
|
|
|
+template <class P>
|
|
|
|
|
+void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id) {
|
|
|
|
|
+ Buffer& new_buffer = slot_buffers[new_buffer_id];
|
|
|
|
|
+ Buffer& overlap = slot_buffers[overlap_id];
|
|
|
|
|
|
|
|
- std::vector<BufferCopy> copies;
|
|
|
|
|
- const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr();
|
|
|
|
|
- overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) {
|
|
|
|
|
- copies.push_back(BufferCopy{
|
|
|
|
|
- .src_offset = begin,
|
|
|
|
|
- .dst_offset = dst_base_offset + begin,
|
|
|
|
|
- .size = range_size,
|
|
|
|
|
- });
|
|
|
|
|
- new_buffer.UnmarkRegionAsCpuModified(begin, range_size);
|
|
|
|
|
- new_buffer.MarkRegionAsGpuModified(begin, range_size);
|
|
|
|
|
|
|
+ std::vector<BufferCopy> copies;
|
|
|
|
|
+ const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr();
|
|
|
|
|
+ overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) {
|
|
|
|
|
+ copies.push_back(BufferCopy{
|
|
|
|
|
+ .src_offset = begin,
|
|
|
|
|
+ .dst_offset = dst_base_offset + begin,
|
|
|
|
|
+ .size = range_size,
|
|
|
});
|
|
});
|
|
|
- if (!copies.empty()) {
|
|
|
|
|
- runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies);
|
|
|
|
|
- }
|
|
|
|
|
- ReplaceBufferDownloads(overlap_id, new_buffer_id);
|
|
|
|
|
- DeleteBuffer(overlap_id);
|
|
|
|
|
|
|
+ new_buffer.UnmarkRegionAsCpuModified(begin, range_size);
|
|
|
|
|
+ new_buffer.MarkRegionAsGpuModified(begin, range_size);
|
|
|
|
|
+ });
|
|
|
|
|
+ if (!copies.empty()) {
|
|
|
|
|
+ runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies);
|
|
|
|
|
+ }
|
|
|
|
|
+ ReplaceBufferDownloads(overlap_id, new_buffer_id);
|
|
|
|
|
+ DeleteBuffer(overlap_id);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template <class P>
|
|
|
|
|
+BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
|
|
|
|
|
+ const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size);
|
|
|
|
|
+ const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
|
|
|
|
+ const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size);
|
|
|
|
|
+ for (const BufferId overlap_id : overlap.ids) {
|
|
|
|
|
+ JoinOverlap(new_buffer_id, overlap_id);
|
|
|
}
|
|
}
|
|
|
Register(new_buffer_id);
|
|
Register(new_buffer_id);
|
|
|
return new_buffer_id;
|
|
return new_buffer_id;
|