mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
Publish synchronous buffer downloads inline after ordered completion
This commit is contained in:
+14
-8
@@ -110,6 +110,7 @@ void BufferCache::DeleteBuffer(BufferId id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool async>
|
||||||
bool BufferCache::DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t size) {
|
bool BufferCache::DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t size) {
|
||||||
std::vector<vk::BufferCopy> copies;
|
std::vector<vk::BufferCopy> copies;
|
||||||
uint64_t total_size = 0;
|
uint64_t total_size = 0;
|
||||||
@@ -170,14 +171,22 @@ bool BufferCache::DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t
|
|||||||
vk::PipelineStageFlagBits::eAllCommands |
|
vk::PipelineStageFlagBits::eAllCommands |
|
||||||
vk::PipelineStageFlagBits::eHost,
|
vk::PipelineStageFlagBits::eHost,
|
||||||
{}, 0, nullptr, 1, &after, 0, nullptr);
|
{}, 0, nullptr, 1, &after, 0, nullptr);
|
||||||
m_scheduler.DeferPriorityOperation([this, mapped, offset, total_size, buffer_address,
|
auto publish = [this, mapped, offset, total_size, buffer_address,
|
||||||
copies = std::move(copies), owner = std::move(temporary)] {
|
copies = std::move(copies), owner = std::move(temporary)] {
|
||||||
(owner ? *owner : m_download_buffer).Invalidate(offset, total_size);
|
(owner ? *owner : m_download_buffer).Invalidate(offset, total_size);
|
||||||
for (const auto& copy: copies) {
|
for (const auto& copy: copies) {
|
||||||
Libs::LibKernel::Memory::WriteBacking(buffer_address + copy.srcOffset,
|
Libs::LibKernel::Memory::WriteBacking(buffer_address + copy.srcOffset,
|
||||||
mapped + (copy.dstOffset - offset), copy.size);
|
mapped + (copy.dstOffset - offset), copy.size);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
if constexpr (async) {
|
||||||
|
m_scheduler.DeferPriorityOperation(std::move(publish));
|
||||||
|
} else {
|
||||||
|
const auto tick = m_scheduler.CurrentTick();
|
||||||
|
m_scheduler.Wait(tick);
|
||||||
|
m_scheduler.WaitPriorityOperations(tick);
|
||||||
|
publish();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,10 +265,7 @@ void BufferCache::ReadMemory(uint64_t vaddr, uint64_t size, bool is_write) {
|
|||||||
const auto window_begin = std::max(Common::AlignDown(vaddr, WindowSize), buffer_begin);
|
const auto window_begin = std::max(Common::AlignDown(vaddr, WindowSize), buffer_begin);
|
||||||
const auto window_end = std::min(std::max(window_begin + WindowSize, vaddr + size), buffer_end);
|
const auto window_end = std::min(std::max(window_begin + WindowSize, vaddr + size), buffer_end);
|
||||||
|
|
||||||
if (DownloadBufferMemory(buffer, window_begin, window_end - window_begin)) {
|
if (DownloadBufferMemory<false>(buffer, window_begin, window_end - window_begin)) {
|
||||||
const auto tick = m_scheduler.CurrentTick();
|
|
||||||
m_scheduler.Wait(tick);
|
|
||||||
m_scheduler.WaitPriorityOperations(tick);
|
|
||||||
m_memory_tracker.UnmarkRegionAsGpuModified(window_begin, window_end - window_begin);
|
m_memory_tracker.UnmarkRegionAsGpuModified(window_begin, window_end - window_begin);
|
||||||
}
|
}
|
||||||
if (is_write) {
|
if (is_write) {
|
||||||
@@ -614,7 +620,7 @@ void BufferCache::RunGarbageCollector() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
EXIT_IF(!DownloadBufferMemory(buffer, buffer.CpuAddress(), buffer.Size()));
|
EXIT_NOT_IMPLEMENTED(!DownloadBufferMemory<true>(buffer, buffer.CpuAddress(), buffer.Size()));
|
||||||
dirty_buffers.push_back(id);
|
dirty_buffers.push_back(id);
|
||||||
} else {
|
} else {
|
||||||
m_memory_tracker.UntrackMemory(buffer.CpuAddress(), buffer.Size());
|
m_memory_tracker.UntrackMemory(buffer.CpuAddress(), buffer.Size());
|
||||||
|
|||||||
+2
-1
@@ -117,7 +117,8 @@ private:
|
|||||||
[[nodiscard]] vk::Buffer UploadCopies(Buffer& buffer, std::span<vk::BufferCopy> copies,
|
[[nodiscard]] vk::Buffer UploadCopies(Buffer& buffer, std::span<vk::BufferCopy> copies,
|
||||||
uint64_t total_size);
|
uint64_t total_size);
|
||||||
[[nodiscard]] bool SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uint64_t size);
|
[[nodiscard]] bool SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uint64_t size);
|
||||||
// Queues backing publication; callers wait before clearing dirty pages or reusing their data.
|
// Synchronous downloads publish before returning; asynchronous callers wait before reuse.
|
||||||
|
template <bool async>
|
||||||
[[nodiscard]] bool DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t size);
|
[[nodiscard]] bool DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t size);
|
||||||
|
|
||||||
GraphicContext& m_graphics;
|
GraphicContext& m_graphics;
|
||||||
|
|||||||
@@ -4208,7 +4208,30 @@ public:
|
|||||||
cache.FillBuffer(base + offset, sizeof(window_value), window_value,
|
cache.FillBuffer(base + offset, sizeof(window_value), window_value,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
const auto window_publication_tick = scheduler.CurrentTick();
|
||||||
|
std::binary_semaphore window_publication_entered{0};
|
||||||
|
std::binary_semaphore release_window_publication{0};
|
||||||
|
std::atomic<bool> window_readback_returned{false};
|
||||||
|
scheduler.DeferPriorityOperation([&] {
|
||||||
|
window_publication_entered.release();
|
||||||
|
release_window_publication.acquire();
|
||||||
|
Libs::LibKernel::Memory::WriteBacking(
|
||||||
|
base + window_inside_offset, &window_stale, sizeof(window_stale));
|
||||||
|
});
|
||||||
|
std::jthread release_window_callback([&] {
|
||||||
|
window_publication_entered.acquire();
|
||||||
|
const auto deadline = std::chrono::steady_clock::now() +
|
||||||
|
std::chrono::milliseconds(100);
|
||||||
|
while (!window_readback_returned.load() &&
|
||||||
|
std::chrono::steady_clock::now() < deadline) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
release_window_publication.release();
|
||||||
|
});
|
||||||
cache.ReadMemory(base + window_fault_offset, sizeof(window_value));
|
cache.ReadMemory(base + window_fault_offset, sizeof(window_value));
|
||||||
|
window_readback_returned = true;
|
||||||
|
release_window_callback.join();
|
||||||
|
scheduler.WaitPriorityOperations(window_publication_tick);
|
||||||
uint32_t window_inside_backing = 0;
|
uint32_t window_inside_backing = 0;
|
||||||
uint32_t window_outside_backing = 0;
|
uint32_t window_outside_backing = 0;
|
||||||
Libs::LibKernel::Memory::TryReadBacking(base + window_inside_offset,
|
Libs::LibKernel::Memory::TryReadBacking(base + window_inside_offset,
|
||||||
@@ -4217,7 +4240,7 @@ public:
|
|||||||
Libs::LibKernel::Memory::TryReadBacking(base + window_outside_offset,
|
Libs::LibKernel::Memory::TryReadBacking(base + window_outside_offset,
|
||||||
&window_outside_backing,
|
&window_outside_backing,
|
||||||
sizeof(window_outside_backing));
|
sizeof(window_outside_backing));
|
||||||
Require(name, "widened-window boundary",
|
Require(name, "widened-window publication order and boundary",
|
||||||
window_inside_backing == window_value &&
|
window_inside_backing == window_value &&
|
||||||
window_outside_backing == window_stale &&
|
window_outside_backing == window_stale &&
|
||||||
!cache.HasGpuDirtyBytes(base + window_inside_offset,
|
!cache.HasGpuDirtyBytes(base + window_inside_offset,
|
||||||
@@ -4228,7 +4251,8 @@ public:
|
|||||||
sizeof(window_value)) &&
|
sizeof(window_value)) &&
|
||||||
cache.IsRegionGpuModified(base + window_outside_offset,
|
cache.IsRegionGpuModified(base + window_outside_offset,
|
||||||
sizeof(window_value)),
|
sizeof(window_value)),
|
||||||
"readback did not honor the clamped half-open 512 KiB window");
|
"readback did not publish after the older overlapping callback "
|
||||||
|
"or honor the clamped half-open 512 KiB window");
|
||||||
cache.ReadMemory(base + window_outside_offset, sizeof(window_value));
|
cache.ReadMemory(base + window_outside_offset, sizeof(window_value));
|
||||||
|
|
||||||
Libs::LibKernel::Memory::WriteBacking(base + first_offset, &first_stale,
|
Libs::LibKernel::Memory::WriteBacking(base + first_offset, &first_stale,
|
||||||
|
|||||||
Reference in New Issue
Block a user