From 054cf422026b7ac81e37deb14db2cbcb0b53904a Mon Sep 17 00:00:00 2001 From: milescoviello Date: Mon, 19 Oct 2026 12:01:48 +0000 Subject: [PATCH] fix(agc): give copied guest buffer regions transfer-source usage A guest buffer region that is copied rather than imported gets a buffer with storage (and, when addressable, device-address) usage only. Host imports, sparse imports and chunk imports carry VK_BUFFER_USAGE_TRANSFER_SRC_BIT, so a buffer view of imported guest memory can be read back with vkCmdCopyBuffer, but not one of a copied region. agc_sparse_run_import_copied does that readback, and the Khronos validation layer reports VUID-vkCmdCopyBuffer-srcBuffer-00118 for it. Copied regions now carry transfer-source usage too. The sparse buffer hole tests seed the buffer pool with the usage a copied region asks for, so their seed buffer gets transfer-source usage as well. Co-Authored-By: Claude Opus 5.5 --- .../libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp | 2 +- core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp | 2 +- .../prx/libSceAgcDriver/tests/execution/SparseBufferHoles.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp index 880056417d5a..092d27021147 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp @@ -4450,7 +4450,7 @@ void GuestBufferMemory::UploadFinish(bool addressable) { void GuestBufferMemory::copyRegion(Region& region, bool addressable) { static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr; const auto bytes = region.end - region.begin; - const auto usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | (addressable ? VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT : 0u); + const auto usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | (addressable ? VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT : 0u); std::uint64_t readBytes = 0; bool inImport = false; if (profile && context.hostImportAlignment != 0) { diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp index d8fffa7de387..6ce939353e30 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp @@ -1826,7 +1826,7 @@ bool RunSparseBufferHoleTests(const Context& context, const BdaTestAccess& acces std::memset(reservation.data + 2 * unit, 0x72, unit); VkBuffer seeded = VK_NULL_HANDLE; { - Buffer seed(context, copied, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + Buffer seed(context, copied, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); std::fill(seed.Bytes().begin(), seed.Bytes().end(), std::byte{0xa5}); seeded = seed.Handle(); } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/SparseBufferHoles.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/SparseBufferHoles.cpp index a7a25f9f8851..64835ea37044 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/SparseBufferHoles.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/SparseBufferHoles.cpp @@ -325,7 +325,7 @@ void Run(const Context& context, const CopyPipeline& pipeline, bool writable, co std::memset(readback.Bytes().data(), 0xcc, BufferBytes); VkBuffer primed = VK_NULL_HANDLE; { - Buffer earlier(context, BufferBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + Buffer earlier(context, BufferBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); primed = earlier.Handle(); std::memset(earlier.Bytes().data(), 0xa5, BufferBytes); }