From 37501b5a787e64d48312cd864a2aa6f98529d832 Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 29 Sep 2026 03:30:51 +0400 Subject: [PATCH] graphics: stream clean guest buffers without backing-store lookups --- .../host_gpu/renderer/cache/bufferCache.cpp | 3 +- tests/ShaderRecompilerComputeTests.cpp | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp index b1a891635..66eef8e9e 100644 --- a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp @@ -454,7 +454,8 @@ std::pair BufferCache::ObtainBuffer(uint64_t vaddr, uint64_t const auto alignment = std::max( 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(vaddr), size); m_stream_buffer.Commit(); return {&m_stream_buffer, offset}; } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 26ae5abcc..4c0cbbcd8 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -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 stream_values{0x13579bdfu, 0x2468ace0u}; + std::memcpy(reinterpret_cast(stream_address), stream_values.data(), + sizeof(stream_values)); + Require(name, "GPU-readable stream source", + Libs::LibKernel::Memory::KernelMprotect( + reinterpret_cast(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(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;