summaryrefslogtreecommitdiffstats
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_cache.h70
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h12
2 files changed, 55 insertions, 27 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index f0f450edb..9b2698fad 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -272,13 +272,19 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad
if (!cpu_addr) {
return {&slot_buffers[NULL_BUFFER_ID], 0};
}
- const BufferId buffer_id = FindBuffer(*cpu_addr, size);
+ return ObtainCPUBuffer(*cpu_addr, size, sync_info, post_op);
+}
+
+template <class P>
+std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
+ VAddr cpu_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) {
+ const BufferId buffer_id = FindBuffer(cpu_addr, size);
Buffer& buffer = slot_buffers[buffer_id];
// synchronize op
switch (sync_info) {
case ObtainBufferSynchronize::FullSynchronize:
- SynchronizeBuffer(buffer, *cpu_addr, size);
+ SynchronizeBuffer(buffer, cpu_addr, size);
break;
default:
break;
@@ -286,18 +292,21 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad
switch (post_op) {
case ObtainBufferOperation::MarkAsWritten:
- MarkWrittenBuffer(buffer_id, *cpu_addr, size);
+ MarkWrittenBuffer(buffer_id, cpu_addr, size);
break;
case ObtainBufferOperation::DiscardWrite: {
- IntervalType interval{*cpu_addr, size};
+ VAddr cpu_addr_start = Common::AlignDown(cpu_addr, 64);
+ VAddr cpu_addr_end = Common::AlignUp(cpu_addr + size, 64);
+ IntervalType interval{cpu_addr_start, cpu_addr_end};
ClearDownload(interval);
+ common_ranges.subtract(interval);
break;
}
default:
break;
}
- return {&buffer, buffer.Offset(*cpu_addr)};
+ return {&buffer, buffer.Offset(cpu_addr)};
}
template <class P>
@@ -535,7 +544,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
it++;
}
- boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads;
+ boost::container::small_vector<std::pair<BufferCopy, BufferId>, 16> downloads;
u64 total_size_bytes = 0;
u64 largest_copy = 0;
for (const IntervalSet& intervals : committed_ranges) {
@@ -905,6 +914,11 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
const u32 offset = buffer.Offset(binding.cpu_addr);
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
+
+ if (is_written) {
+ MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
+ }
+
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
runtime.BindStorageBuffer(stage, binding_index, buffer, offset, size, is_written);
++binding_index;
@@ -922,6 +936,11 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
+ const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0;
+ if (is_written) {
+ MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
+ }
+
const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -953,6 +972,8 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
+ MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
+
const u32 offset = buffer.Offset(binding.cpu_addr);
host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset);
@@ -1002,6 +1023,11 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
const u32 offset = buffer.Offset(binding.cpu_addr);
const bool is_written =
((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
+
+ if (is_written) {
+ MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
+ }
+
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
runtime.BindComputeStorageBuffer(binding_index, buffer, offset, size, is_written);
++binding_index;
@@ -1019,6 +1045,12 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
+ const bool is_written =
+ ((channel_state->written_compute_texture_buffers >> index) & 1) != 0;
+ if (is_written) {
+ MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
+ }
+
const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -1159,6 +1191,11 @@ void BufferCache<P>::UpdateDrawIndirect() {
.size = static_cast<u32>(size),
.buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)),
};
+ VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
+ VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
+ IntervalType interval{cpu_addr_start, cpu_addr_end};
+ ClearDownload(interval);
+ common_ranges.subtract(interval);
};
if (current_draw_indirect->include_count) {
update(current_draw_indirect->count_start_address, sizeof(u32),
@@ -1187,16 +1224,11 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) {
template <class P>
void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
- const u32 written_mask = channel_state->written_storage_buffers[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.cpu_addr, binding.size);
binding.buffer_id = buffer_id;
- // Mark buffer as written if needed
- if (((written_mask >> index) & 1) != 0) {
- MarkWrittenBuffer(buffer_id, binding.cpu_addr, binding.size);
- }
});
}
@@ -1205,10 +1237,6 @@ void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
Binding& binding = channel_state->texture_buffers[stage][index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
- // Mark buffer as written if needed
- if (((channel_state->written_texture_buffers[stage] >> index) & 1) != 0) {
- MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
- }
});
}
@@ -1238,7 +1266,6 @@ void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
.size = size,
.buffer_id = buffer_id,
};
- MarkWrittenBuffer(buffer_id, *cpu_addr, size);
}
template <class P>
@@ -1265,10 +1292,6 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
// Resolve buffer
Binding& binding = channel_state->compute_storage_buffers[index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
- // Mark as written if needed
- if (((channel_state->written_compute_storage_buffers >> index) & 1) != 0) {
- MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
- }
});
}
@@ -1277,18 +1300,11 @@ void BufferCache<P>::UpdateComputeTextureBuffers() {
ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) {
Binding& binding = channel_state->compute_texture_buffers[index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
- // Mark as written if needed
- if (((channel_state->written_compute_texture_buffers >> index) & 1) != 0) {
- MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
- }
});
}
template <class P>
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
- if (memory_tracker.IsRegionCpuModified(cpu_addr, size)) {
- SynchronizeBuffer(slot_buffers[buffer_id], cpu_addr, size);
- }
memory_tracker.MarkRegionAsGpuModified(cpu_addr, size);
const IntervalType base_interval{cpu_addr, cpu_addr + size};
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index fdc26688d..eed267361 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -299,6 +299,10 @@ public:
[[nodiscard]] std::pair<Buffer*, u32> ObtainBuffer(GPUVAddr gpu_addr, u32 size,
ObtainBufferSynchronize sync_info,
ObtainBufferOperation post_op);
+
+ [[nodiscard]] std::pair<Buffer*, u32> ObtainCPUBuffer(VAddr gpu_addr, u32 size,
+ ObtainBufferSynchronize sync_info,
+ ObtainBufferOperation post_op);
void FlushCachedWrites();
/// Return true when there are uncommitted buffers to be downloaded
@@ -339,6 +343,14 @@ public:
[[nodiscard]] std::pair<Buffer*, u32> GetDrawIndirectBuffer();
+ template <typename Func>
+ void BufferOperations(Func&& func) {
+ do {
+ channel_state->has_deleted_buffers = false;
+ func();
+ } while (channel_state->has_deleted_buffers);
+ }
+
std::recursive_mutex mutex;
Runtime& runtime;