From 8a9a741b684469cce9997266ed44d7e2d0e53aea Mon Sep 17 00:00:00 2001 From: Himansh Raj Date: Mon, 26 Oct 2026 07:19:28 +0530 Subject: [PATCH] fix(agc): clear a reused pooled buffer's unused tail on macOS MoltenVK has no robustBufferAccess2, so a robust read past the end of a pooled buffer is clamped into its slot instead of returning zero. A 100-byte buffer placed in a 256-byte slot then read the bytes an earlier user left there (0xabababab), and agc_driver_pooled_buffer_range failed. On macOS, when a host-coherent mapped slot is handed to a new buffer, the bytes past the requested size are cleared to zero. Linux and Windows compile the same code as before. --- .../libSceAgcDriver/Graphics/src/Resources.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp index ea37fed7ef..8dbb767364 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp @@ -6,11 +6,22 @@ #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include #include +#ifdef __APPLE__ +#include +#include +#endif namespace AgcDriver::Graphics { namespace { +#ifdef __APPLE__ +void ClearPooledTail(void* mapping, std::size_t size, VkDeviceSize mappedBytes, VkMemoryPropertyFlags properties) { + if (mapping == nullptr || (properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0 || mappedBytes <= size) return; + std::memset(static_cast(mapping) + size, 0, static_cast(mappedBytes - size)); +} + +#endif VkDeviceSize ClassAllocationBytes(const VkMemoryRequirements& requirements, std::size_t capacity) { const auto alignment = std::max(requirements.alignment, 1); return std::max(requirements.size, (static_cast(capacity) + alignment - 1) / alignment * alignment); @@ -52,6 +63,9 @@ Buffer::Buffer(const Context& context, std::size_t size, VkBufferUsageFlags usag capacity = allocation->bytes; offset = allocation->offset; slab = allocation->slab; +#ifdef __APPLE__ + ClearPooledTail(mapping, size, std::min(capacity, allocationBytes), properties); +#endif if (allocation->bufferBytes != size) { context.Function("vkDestroyBuffer")(context.device, buffer, nullptr); buffer = VK_NULL_HANDLE; @@ -93,6 +107,9 @@ Buffer::Buffer(const Context& context, std::size_t size, VkBufferUsageFlags usag Check(context.Function("vkBindBufferMemory")(context.device, buffer, memory, offset), "vkBindBufferMemory slab"); initializeAddress(usage); mapping = slot.mapping; +#ifdef __APPLE__ + ClearPooledTail(mapping, size, capacity, properties); +#endif ready = true; return; }