From 0a88e761eb8a3c04f548f5724b80c0777be34868 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 1 Oct 2026 00:19:46 -0400 Subject: [PATCH] Port UMA part 1 --- src/video_core/buffer_cache/buffer_cache.h | 14 +++++++++ .../renderer_vulkan/vk_buffer_cache.cpp | 31 +++++++++++++++++-- .../renderer_vulkan/vk_buffer_cache.h | 19 ++++++++++++ .../vulkan_common/vulkan_device.cpp | 9 ++++++ src/video_core/vulkan_common/vulkan_device.h | 5 +++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 087d7ac1f8..734ec5e0f3 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1876,6 +1876,20 @@ void BufferCache

::MappedUploadMemory([[maybe_unused]] Buffer& buffer, [[maybe_unused]] u64 total_size_bytes, [[maybe_unused]] std::span copies) { if constexpr (USE_MEMORY_MAPS) { + if constexpr (requires { runtime.DirectUploadSpan(buffer, copies); }) { + const std::span direct = runtime.DirectUploadSpan(buffer, copies); + if (!direct.empty()) { + for (const BufferCopy& copy : copies) { + const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; + if (Settings::values.enable_gpu_buffer_readback.GetValue()) { + DownloadBufferMemory(buffer, device_addr, copy.size); + } + device_memory.ReadBlockUnsafe(device_addr, direct.data() + copy.dst_offset, + copy.size); + } + return; + } + } auto upload_staging = runtime.UploadStagingBuffer(total_size_bytes); const std::span staging_pointer = upload_staging.mapped_span; for (BufferCopy& copy : copies) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 77e33d1354..f35ee502ce 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -97,10 +97,14 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, }; - if (sparse_alignment > 1) { - return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal, sparse_alignment); + MemoryUsage usage = MemoryUsage::DeviceLocal; + if (device.IsUMA()) { + usage = MemoryUsage::Stream; } - return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal); + if (sparse_alignment > 1) { + return memory_allocator.CreateBuffer(buffer_ci, usage, sparse_alignment); + } + return memory_allocator.CreateBuffer(buffer_ci, usage); } } // Anonymous namespace @@ -138,6 +142,17 @@ void Buffer::MarkUsage(u64 offset, u64 size) noexcept { last_usage_tick = scheduler->CurrentTick(); } +void Buffer::MarkUpload() noexcept { + last_upload_tick = scheduler->CurrentTick(); +} + +std::span Buffer::CoherentMapping() noexcept { + if (!buffer.IsHostCoherent()) { + return {}; + } + return buffer.Mapped(); +} + VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) { if (!device) { // Null buffer supported, return a null descriptor @@ -496,6 +511,16 @@ bool BufferCacheRuntime::CanReorderUpload(const Buffer& buffer, return can_use_upload_cmdbuf; } +std::span BufferCacheRuntime::DirectUploadSpan( + Buffer& buffer, std::span copies) { + const std::span mapping = buffer.CoherentMapping(); + if (mapping.empty() || !scheduler.IsFree(buffer.LastUploadTick()) || + !CanReorderUpload(buffer, copies)) { + return {}; + } + return mapping; +} + void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, std::span copies, bool barrier, bool can_reorder_upload) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 2f40cc2ac1..d96bd3783a 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -69,6 +69,14 @@ public: return last_usage_tick; } + void MarkUpload() noexcept; + + [[nodiscard]] u64 LastUploadTick() const noexcept { + return last_upload_tick; + } + + [[nodiscard]] std::span CoherentMapping() noexcept; + operator VkBuffer() const noexcept { return *buffer; } @@ -88,6 +96,7 @@ private: VideoCommon::UsageTracker tracker; VkDeviceAddress device_address{}; u64 last_usage_tick{}; + u64 last_upload_tick{}; bool is_null{}; bool sparse_compatible{}; }; @@ -140,6 +149,9 @@ public: bool CanReorderUpload(const Buffer& buffer, std::span copies); + [[nodiscard]] std::span DirectUploadSpan(Buffer& buffer, + std::span copies); + void FreeDeferredStagingBuffer(StagingBufferRef& ref); void PreCopyBarrier(); @@ -148,6 +160,13 @@ public: std::span copies, bool barrier, bool can_reorder_upload = false); + void CopyBuffer(Buffer& dst_buffer, VkBuffer src_buffer, + std::span copies, bool barrier, + bool can_reorder_upload = false) { + dst_buffer.MarkUpload(); + CopyBuffer(dst_buffer.Handle(), src_buffer, copies, barrier, can_reorder_upload); + } + void PostCopyBarrier(); void ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value); diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index b3969fd77d..e9075a62b5 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -487,6 +487,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR properties.subgroup_size_control.maxSubgroupSize > GuestWarpSize; is_integrated = properties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + const VkPhysicalDeviceMemoryProperties memory_properties = + physical.GetMemoryProperties().memoryProperties; + is_uma = std::all_of(memory_properties.memoryTypes, + memory_properties.memoryTypes + memory_properties.memoryTypeCount, + [](const VkMemoryType& type) { + return (type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == + 0 || + (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; + }); supports_d24_depth = IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT, diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index fa230fa0f4..b562c210e5 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -984,6 +984,10 @@ FN_MAX_LIMIT_LIST return must_emulate_scaled_formats; } + bool IsUMA() const { + return is_uma; + } + bool HasNullDescriptor() const { return features.robustness2.nullDescriptor; } @@ -1198,6 +1202,7 @@ private: bool is_blit_depth32_stencil8_supported{}; ///< Support for blitting from and to D32S8. bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest. bool is_integrated{}; ///< Is GPU an iGPU. + bool is_uma{}; bool has_broken_compute{}; ///< Compute shaders can cause crashes bool has_broken_cube_compatibility{}; ///< Has broken cube compatibility bit bool has_broken_float16_math{};