renderer: avoid allocating for dirty range probes

This commit is contained in:
nmzik
2026-08-23 17:38:31 +02:00
parent 30fa9dddc5
commit cb378365e1
3 changed files with 19 additions and 9 deletions
+9
View File
@@ -59,6 +59,15 @@ public:
return result;
}
[[nodiscard]] bool Intersects(uint64_t address, uint64_t size) const {
const auto end = End(address, size);
auto it = m_ranges.lower_bound(address);
if (it != m_ranges.begin() && std::prev(it)->second > address) {
return true;
}
return it != m_ranges.end() && it->first < end;
}
[[nodiscard]] bool Contains(uint64_t address, uint64_t size) const {
const auto end = End(address, size);
auto it = m_ranges.upper_bound(address);
+6 -9
View File
@@ -167,7 +167,7 @@ void BufferCache::QueueGarbageDownload(std::span<const DownloadCopy> copies, Buf
// query therefore cannot orphan a dirty sibling on an edge page.
m_memory_tracker.UnmarkRegionAsGpuModified(address, size);
if (m_memory_tracker.IsRegionGpuModified(address, size) ||
!m_gpu_modified_ranges.Intersections(address, size).empty()) {
m_gpu_modified_ranges.Intersects(address, size)) {
EXIT("BufferCache: asynchronous garbage collection retained GPU ownership\n");
}
m_memory_tracker.UntrackMemory(address, size);
@@ -314,8 +314,7 @@ void BufferCache::UnmapMemory(uint64_t vaddr, uint64_t size) {
!m_memory_tracker.IsRegionGpuModified(begin, buffer.Size())) {
continue;
}
const auto dirty = m_gpu_modified_ranges.Intersections(begin, buffer.Size());
if (dirty.empty()) {
if (!m_gpu_modified_ranges.Intersects(begin, buffer.Size())) {
EXIT("BufferCache: GPU-modified buffer has no dirty ranges\n");
}
modified_buffers.emplace_back(begin, buffer.Size());
@@ -350,7 +349,7 @@ void BufferCache::UnmapMemory(uint64_t vaddr, uint64_t size) {
for (const auto& [begin, bytes]: retired_buffers) {
m_memory_tracker.MarkRegionAsCpuModified(begin, bytes);
}
if (!m_gpu_modified_ranges.Intersections(vaddr, size).empty()) {
if (m_gpu_modified_ranges.Intersects(vaddr, size)) {
EXIT("BufferCache: unmap retained dirty byte ranges\n");
}
m_memory_tracker.UntrackMemory(vaddr, size);
@@ -557,8 +556,7 @@ std::pair<Buffer*, uint64_t> BufferCache::ObtainBufferForImage(uint64_t vaddr, u
{
const bool cpu_modified = m_memory_tracker.IsRegionCpuModified(vaddr, size);
const bool gpu_modified = m_memory_tracker.IsRegionGpuModified(vaddr, size);
const auto dirty = m_gpu_modified_ranges.Intersections(vaddr, size);
const bool has_dirty_buffer_source = !dirty.empty();
const bool has_dirty_buffer_source = m_gpu_modified_ranges.Intersects(vaddr, size);
m_memory_tracker.ValidateGpuDirtyOwnership(m_gpu_modified_ranges, vaddr, size,
"image source");
@@ -592,8 +590,7 @@ std::pair<Buffer*, uint64_t> BufferCache::ObtainBufferForImage(uint64_t vaddr, u
}
m_staging_buffer.Commit();
const auto dirty = m_gpu_modified_ranges.Intersections(vaddr, size);
const bool has_dirty_buffer_source = !dirty.empty();
const bool has_dirty_buffer_source = m_gpu_modified_ranges.Intersects(vaddr, size);
auto* owner = find_owner();
if (has_dirty_buffer_source && owner == nullptr) {
EXIT("BufferCache: GPU-dirty image source lost its native owner\n");
@@ -756,7 +753,7 @@ bool BufferCache::IsRegionGpuModified(uint64_t vaddr, uint64_t size) {
}
bool BufferCache::HasGpuDirtyBytes(uint64_t vaddr, uint64_t size) {
return !m_gpu_modified_ranges.Intersections(vaddr, size).empty();
return m_gpu_modified_ranges.Intersects(vaddr, size);
}
bool BufferCache::IsRegionCpuModified(uint64_t vaddr, uint64_t size) {
+4
View File
@@ -191,6 +191,10 @@ void TestRangeSet() {
ranges.Add(0x1200, 0x40);
Check(ranges.Contains(0x1010, 0xe0) && !ranges.Contains(0x1010, 0x200),
"range set containment did not require full coverage");
Check(ranges.Intersects(0x0fff, 2) && ranges.Intersects(0x11ff, 2) &&
!ranges.Intersects(0x1100, 0x100) &&
!ranges.Intersects(0x1240, 1),
"range set intersection did not preserve half-open boundaries");
auto intersections = ranges.Intersections(0x1070, 0x1b0);
Check(intersections.size() == 2 && intersections[0].address == 0x1070 &&
intersections[0].size == 0x90 &&