diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index d7eb21612f..6b2a37ea8c 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h @@ -129,13 +129,24 @@ public: write_tick = write_tick_; } + u64 ContentSerial() const noexcept { + return content_serial; + } + + void MarkContentModified() noexcept { + content_serial = ++next_content_serial; + } + private: + static inline u64 next_content_serial = 0; + 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; + u64 content_serial = ++next_content_serial; }; } // namespace VideoCommon diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index eb214af50e..89d0003207 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -266,6 +266,7 @@ bool BufferCache
::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am const auto& copy = copies[0]; src_buffer.MarkUsage(copy.src_offset, copy.size); dest_buffer.MarkUsage(copy.dst_offset, copy.size); + dest_buffer.MarkContentModified(); runtime.CopyBuffer(dest_buffer, src_buffer, copies, true); if (has_new_downloads) { memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount); @@ -297,6 +298,7 @@ bool BufferCache
::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) { const u32 offset = dest_buffer.Offset(*cpu_dst_address); runtime.ClearBuffer(dest_buffer, offset, size, value); dest_buffer.MarkUsage(offset, size); + dest_buffer.MarkContentModified(); return true; } @@ -773,6 +775,7 @@ void BufferCache
::BindHostIndexBuffer() {
if (draw_state.inline_index_draw_indexes.empty()) {
SynchronizeBuffer(buffer, channel_state->index_buffer.device_addr, size);
} else {
+ buffer.MarkContentModified();
if constexpr (USE_MEMORY_MAPS_FOR_UPLOADS) {
auto upload_staging = runtime.UploadStagingBuffer(size);
std::array ::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
template ::ResolveMultiRangeStorage(Binding& binding,
- std::vector ::ResolveMultiRangeStorage(Binding& binding,
if (!found || found->size() < 2) {
return;
}
- const VirtualSegments segments = *found;
+ const VirtualSegments& segments = *found;
const u32 first = static_cast ::BindMultiRangeStorage(const Binding& binding, bool is_writt
const MultiRangeSegment& segment = pool[binding.segment_first + index];
Buffer& buffer = slot_buffers[segment.buffer_id];
TouchBuffer(buffer, segment.buffer_id);
- if (SynchronizeBuffer(buffer, segment.device_addr, segment.size)) {
- runtime.InvalidateMultiRange(key);
- }
+ SynchronizeBuffer(buffer, segment.device_addr, segment.size);
const u32 offset = buffer.Offset(segment.device_addr);
buffer.MarkUsage(offset, segment.size);
if (is_written) {
@@ -1456,9 +1459,12 @@ void BufferCache ::UpdateStorageBuffers(size_t stage) {
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
// Resolve buffer
Binding& binding = channel_state->storage_buffers[stage][index];
- const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size, false);
- binding.buffer_id = buffer_id;
- ResolveMultiRangeStorage(binding, graphics_segments);
+ const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
+ ResolveMultiRangeStorage(binding, graphics_segments, is_written);
+ binding.buffer_id = NULL_BUFFER_ID;
+ if (binding.segment_count == 0 || is_written) {
+ binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
+ }
});
}
@@ -1521,8 +1527,12 @@ void BufferCache ::UpdateComputeStorageBuffers() {
ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
// Resolve buffer
Binding& binding = channel_state->compute_storage_buffers[index];
- binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
- ResolveMultiRangeStorage(binding, compute_segments);
+ const bool is_written = ((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
+ ResolveMultiRangeStorage(binding, compute_segments, is_written);
+ binding.buffer_id = NULL_BUFFER_ID;
+ if (binding.segment_count == 0 || is_written) {
+ binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
+ }
});
}
@@ -1539,6 +1549,7 @@ void BufferCache ::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u3
if constexpr (!IS_OPENGL) {
Buffer& buffer = slot_buffers[buffer_id];
buffer.setWriteTick(runtime.CurrentTick());
+ buffer.MarkContentModified();
}
memory_tracker.MarkRegionAsGpuModified(device_addr, size);
gpu_modified_ranges.Add(device_addr, size);
@@ -1784,6 +1795,7 @@ bool BufferCache ::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si
template ::UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy,
std::span ::InlineMemoryImplementation(DAddr dest_address, size_t copy_
BufferId buffer_id = FindBuffer(dest_address, static_cast