graphics: stream clean guest buffers without backing-store lookups

This commit is contained in:
nmzik
2026-09-29 03:30:51 +04:00
parent b43bf9f7fb
commit 37501b5a78
2 changed files with 31 additions and 1 deletions
+2 -1
View File
@@ -454,7 +454,8 @@ std::pair<Buffer*, uint64_t> BufferCache::ObtainBuffer(uint64_t vaddr, uint64_t
const auto alignment = std::max<uint64_t>(
m_graphics.physical_device_properties.limits.minUniformBufferOffsetAlignment, 1);
auto [mapped, offset] = m_stream_buffer.Map(size, alignment, false);
if (mapped != nullptr && Libs::LibKernel::Memory::TryReadBacking(vaddr, mapped, size)) {
if (mapped != nullptr) {
std::memcpy(mapped, reinterpret_cast<const void*>(vaddr), size);
m_stream_buffer.Commit();
return {&m_stream_buffer, offset};
}
+29
View File
@@ -3679,6 +3679,35 @@ public:
return value;
};
constexpr uint64_t stream_pages = base + 0x18000;
constexpr uint64_t stream_address = stream_pages + 0x4000 - sizeof(uint32_t);
const std::array<uint32_t, 2> stream_values{0x13579bdfu, 0x2468ace0u};
std::memcpy(reinterpret_cast<void *>(stream_address), stream_values.data(),
sizeof(stream_values));
Require(name, "GPU-readable stream source",
Libs::LibKernel::Memory::KernelMprotect(
reinterpret_cast<void *>(stream_pages), 0x8000, 0x10) == 0 &&
cache.IsRegionCpuModified(stream_address, sizeof(stream_values)) &&
!cache.IsRegionGpuModified(stream_address, sizeof(stream_values)),
"cross-page stream source is not CPU-dirty and GPU-clean");
const auto stream_tick = scheduler.CurrentTick();
const auto [streamed, streamed_offset] =
cache.ObtainBuffer(stream_address, sizeof(stream_values), false);
Require(name, "cross-page read-only stream upload",
streamed == &cache.GetUtilityBuffer(MemoryUsage::Stream) &&
scheduler.CurrentTick() == stream_tick &&
std::memcmp(streamed->Mapped().data() + streamed_offset,
stream_values.data(), sizeof(stream_values)) == 0,
"GPU-readable guest bytes were not streamed without submission");
Require(name, "stream source protection restore",
Libs::LibKernel::Memory::KernelMprotect(
reinterpret_cast<void *>(stream_pages), 0x8000, 0x3) == 0,
"stream source protection was not restored");
Require(name, "streamed GPU bytes",
ReadNativeValue(*streamed, streamed_offset) == stream_values[0] &&
ReadNativeValue(*streamed, streamed_offset + sizeof(uint32_t)) == stream_values[1],
"stream commit did not publish both cross-page words to the GPU");
constexpr uint64_t large_copy_source_offset = 0x40000;
constexpr uint64_t large_copy_destination_offset = 0x80000;
constexpr uint64_t large_copy_size = 96 * 1024;