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.
This commit is contained in:
Himansh Raj committed 2026-10-26 07:19:28 +05:30
1 parent a3987a1eca
commit 8a9a741b68
1 file changed
+17
@@ -6,11 +6,22 @@
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
#include <algorithm>
#include <exception>
#ifdef __APPLE__
#include <cstddef>
#include <cstring>
#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<std::byte*>(mapping) + size, 0, static_cast<std::size_t>(mappedBytes - size));
}
#endif
VkDeviceSize ClassAllocationBytes(const VkMemoryRequirements& requirements, std::size_t capacity) {
const auto alignment = std::max<VkDeviceSize>(requirements.alignment, 1);
return std::max<VkDeviceSize>(requirements.size, (static_cast<VkDeviceSize>(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<VkDeviceSize>(capacity, allocationBytes), properties);
#endif
if (allocation->bufferBytes != size) {
context.Function<PFN_vkDestroyBuffer>("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<PFN_vkBindBufferMemory>("vkBindBufferMemory")(context.device, buffer, memory, offset), "vkBindBufferMemory slab");
initializeAddress(usage);
mapping = slot.mapping;
#ifdef __APPLE__
ClearPooledTail(mapping, size, capacity, properties);
#endif
ready = true;
return;
}