aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/buffer_cache')
-rw-r--r--src/video_core/buffer_cache/buffer_base.h9
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h49
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h2
3 files changed, 43 insertions, 17 deletions
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h
index bec2dac246..d7eb21612f 100644
--- a/src/video_core/buffer_cache/buffer_base.h
+++ b/src/video_core/buffer_cache/buffer_base.h
@@ -121,12 +121,21 @@ public:
return size_bytes;
}
+ u64 getWriteTick() const noexcept {
+ return write_tick;
+ }
+
+ void setWriteTick(u64 write_tick_) {
+ write_tick = write_tick_;
+ }
+
private:
VAddr cpu_addr = 0;
BufferFlagBits flags{};
int stream_score = 0;
size_t lru_id = SIZE_MAX;
size_t size_bytes = 0;
+ u64 write_tick = 0;
};
} // namespace VideoCommon
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 740d99558e..e40aad1fb5 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1430,6 +1430,10 @@ void BufferCache<P>::UpdateComputeTextureBuffers() {
template <class P>
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size) {
+ if constexpr (!IS_OPENGL) {
+ Buffer& buffer = slot_buffers[buffer_id];
+ buffer.setWriteTick(runtime.CurrentTick());
+ }
memory_tracker.MarkRegionAsGpuModified(device_addr, size);
gpu_modified_ranges.Add(device_addr, size);
uncommitted_gpu_modified_ranges.Add(device_addr, size);
@@ -1442,17 +1446,33 @@ BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size) {
}
const u64 page = device_addr >> CACHING_PAGEBITS;
const BufferId buffer_id = page_table[page];
- if (!buffer_id) {
- return CreateBuffer(device_addr, size);
- }
- const Buffer& buffer = slot_buffers[buffer_id];
- if (buffer.IsInBounds(device_addr, size)) {
- return buffer_id;
+ if (buffer_id) {
+ Buffer& buffer = slot_buffers[buffer_id];
+ WaitForGpuFenceIfNeeded(buffer);
+ if (buffer.IsInBounds(device_addr, size)) {
+ return buffer_id;
+ }
}
return CreateBuffer(device_addr, size);
}
template <class P>
+void BufferCache<P>::WaitForGpuFenceIfNeeded(Buffer& buffer) {
+ if constexpr (!IS_OPENGL) {
+ const bool gpu_fence_accurate = Settings::IsGPUFenceBehaviorAccurate();
+ const bool gpu_fence_strict = Settings::IsGPUFenceBehaviorStrict();
+ if (gpu_fence_accurate || gpu_fence_strict) {
+ const u64 gpu_tick_delay = gpu_fence_strict ? 0 : 3;
+ const u64 buffer_tick = buffer.getWriteTick();
+ const u64 gpu_tick = runtime.KnownGpuTick();
+ if (buffer_tick > gpu_tick + gpu_tick_delay) {
+ runtime.Wait(buffer_tick);
+ }
+ }
+ }
+}
+
+template <class P>
typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(DAddr device_addr,
u32 wanted_size) {
static constexpr int STREAM_LEAP_THRESHOLD = 16;
@@ -1634,17 +1654,6 @@ bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si
if (total_size_bytes == 0) {
return true;
}
- if (Settings::values.enable_gpu_buffer_readback.GetValue()) {
- u64 min_offset = (std::numeric_limits<u64>::max)();
- u64 max_offset = 0;
- for (const auto& copy : upload_copies) {
- min_offset = (std::min)(min_offset, copy.dst_offset);
- max_offset = (std::max)(max_offset, copy.dst_offset + copy.size);
- }
- const DAddr sync_addr = buffer.CpuAddr() + min_offset;
- const u64 sync_size = max_offset - min_offset;
- DownloadBufferMemory(buffer, sync_addr, sync_size);
- }
const std::span<BufferCopy> copies_span(upload_copies.data(), upload_copies.size());
UploadMemory(buffer, total_size_bytes, largest_copy, copies_span);
any_buffer_uploaded = true;
@@ -1679,6 +1688,9 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer,
if (immediate_buffer.empty()) {
immediate_buffer = ImmediateBuffer(largest_copy);
}
+ if (Settings::values.enable_gpu_buffer_readback.GetValue()) {
+ DownloadBufferMemory(buffer, device_addr, copy.size);
+ }
device_memory.ReadBlockUnsafe(device_addr, immediate_buffer.data(), copy.size);
upload_span = immediate_buffer.subspan(0, copy.size);
}
@@ -1697,6 +1709,9 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
for (BufferCopy& copy : copies) {
u8* const src_pointer = staging_pointer.data() + copy.src_offset;
const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
+ if (Settings::values.enable_gpu_buffer_readback.GetValue()) {
+ DownloadBufferMemory(buffer, device_addr, copy.size);
+ }
device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size);
// Apply the staging offset
copy.src_offset += upload_staging.offset;
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index 473cc6842e..14ab3e6ebc 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -416,6 +416,8 @@ private:
[[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size);
+ void WaitForGpuFenceIfNeeded(Buffer& buffer);
+
[[nodiscard]] OverlapResult ResolveOverlaps(DAddr device_addr, u32 wanted_size);
void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score);