diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp index fa8240bd6..3174ec625 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp @@ -741,11 +741,38 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) { tail.Upload(true); reject([&] { tail.Descriptor(address + 58, 4, adjustment); }, "exceeds its GPU owner"); } + { + void* plain = GuestHeap::GuestHeapAllocate_nid_postfix(64); + void* gpu = GuestHeap::GuestHeapAlignForGpu_nid_postfix(16, 64); + const auto lookup = [](const void* pointer) { + GuestAllocations::Mutation mutation; + return mutation.Find(pointer); + }; + Require(!lookup(plain).gpu && lookup(gpu).gpu, "a guest heap block's GPU access does not follow how it was allocated"); + gpu = GuestHeap::GuestHeapReallocate_nid_postfix(gpu, 128); + plain = GuestHeap::GuestHeapRealign_nid_postfix(plain, 128, 64); + Require(!lookup(plain).gpu && lookup(gpu).gpu, "a reallocated guest heap block changed its GPU access"); + { + GuestBufferMemory leased(context); + leased.AcquireRegistered(); + leased.Upload(true); + const auto ranges = leased.AddressRanges(); + const auto listed = [&](const void* pointer) { + const auto address = reinterpret_cast(pointer); + return std::any_of(ranges.begin(), ranges.end(), [&](const auto& range) { return range.begin <= address && address < range.end; }); + }; + Require(!listed(plain), "a guest heap block without GPU access is in an address-based build"); + Require(listed(gpu), "a guest heap block with GPU access is missing from an address-based build"); + leased.WriteBack(); + } + GuestHeap::GuestHeapFree_nid_postfix(plain); + GuestHeap::GuestHeapFree_nid_postfix(gpu); + } { // The cached address space: a second build in an unchanged registry takes the first one's // space, and a guest free of a range pinned only by the cache goes through the pin waiter's // drop (no GPU work to wait for) and empties the registry of it. - void* block = GuestHeap::GuestHeapAllocate_nid_postfix(64); + void* block = GuestHeap::GuestHeapAlignForGpu_nid_postfix(16, 64); const auto blockAddress = reinterpret_cast(block); std::memset(block, 0x5a, 64); const auto registered = [&] { diff --git a/core/libs/prx/libSceAgcDriver/tests/Submit.cpp b/core/libs/prx/libSceAgcDriver/tests/Submit.cpp index 4137e06b3..1d3e78ce5 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Submit.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Submit.cpp @@ -451,8 +451,8 @@ std::array memoryCopy(const void* destination, const void* sou void testCopyIntoHostMemory() { constexpr std::size_t words = 32768; constexpr auto bytes = static_cast(words * 4); - auto* produced = static_cast(GuestHeap::GuestHeapAlign_nid_postfix(65536, bytes)); - auto* source = static_cast(GuestHeap::GuestHeapAlign_nid_postfix(65536, bytes)); + auto* produced = static_cast(GuestHeap::GuestHeapAlignForGpu_nid_postfix(65536, bytes)); + auto* source = static_cast(GuestHeap::GuestHeapAlignForGpu_nid_postfix(65536, bytes)); std::vector destination(words); for (const bool label : {false, true}) { for (std::size_t i = 0; i < words; ++i) { diff --git a/core/libs/prx/libSceAvPlayer/src/Player.cpp b/core/libs/prx/libSceAvPlayer/src/Player.cpp index bdf69bfc3..ab1aebb40 100644 --- a/core/libs/prx/libSceAvPlayer/src/Player.cpp +++ b/core/libs/prx/libSceAvPlayer/src/Player.cpp @@ -29,13 +29,17 @@ void APS5_VABI GuestDeallocate_nid_no_patch(void*, void* memory) { GuestHeap::GuestHeapFree_nid_postfix(memory); } +void* APS5_VABI GuestAllocateTexture_nid_no_patch(void*, std::uint32_t alignment, std::uint32_t size) { + return GuestHeap::GuestHeapAlignForGpu_nid_postfix(std::max(alignment, 16), size); +} + AvPlayerMemAllocator WithGuestHeapFallback(AvPlayerMemAllocator memory) { if (!memory.allocate || !memory.deallocate) { memory.allocate = GuestAllocate_nid_no_patch; memory.deallocate = GuestDeallocate_nid_no_patch; } if (!memory.allocate_texture || !memory.deallocate_texture) { - memory.allocate_texture = GuestAllocate_nid_no_patch; + memory.allocate_texture = GuestAllocateTexture_nid_no_patch; memory.deallocate_texture = GuestDeallocate_nid_no_patch; } return memory; diff --git a/core/libs/prx/libc/include/GuestHeap.hpp b/core/libs/prx/libc/include/GuestHeap.hpp index 0c7b87a87..24051f79c 100644 --- a/core/libs/prx/libc/include/GuestHeap.hpp +++ b/core/libs/prx/libc/include/GuestHeap.hpp @@ -13,6 +13,7 @@ void GuestHeapFree_nid_postfix(void* pointer); void* GuestHeapReallocate_nid_postfix(void* pointer, std::size_t bytes); void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes); void* GuestHeapRealign_nid_postfix(void* pointer, std::size_t bytes, std::size_t alignment); +void* GuestHeapAlignForGpu_nid_postfix(std::size_t alignment, std::size_t bytes); } diff --git a/core/libs/prx/libc/src/GuestHeap.cpp b/core/libs/prx/libc/src/GuestHeap.cpp index e651faa3a..b2ae0d13a 100644 --- a/core/libs/prx/libc/src/GuestHeap.cpp +++ b/core/libs/prx/libc/src/GuestHeap.cpp @@ -193,7 +193,7 @@ void rawFree(void* raw, std::size_t blockBytes) { else std::free(raw); } -void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std::size_t bytes) { +void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std::size_t bytes, bool gpu) { if (alignment == 0 || (alignment & (alignment - 1)) != 0) throw std::invalid_argument("invalid guest heap alignment"); alignment = std::max(alignment, MinimumAlignment); const std::size_t padding = alignment > RawAlignment ? alignment : 0; @@ -205,7 +205,7 @@ void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std: reinterpret_cast(pointer)[-2] = raw; reinterpret_cast(pointer)[-1] = blockBytes; try { - mutation.Add(pointer, bytes, true, true, true); + mutation.Add(pointer, bytes, true, true, gpu); } catch (...) { rawFree(raw, blockBytes); throw; @@ -222,7 +222,7 @@ void free(GuestAllocations::Mutation& mutation, void* pointer) { void* GuestHeapAllocate_nid_postfix(std::size_t bytes) { GuestAllocations::Mutation mutation; - return allocate(mutation, MinimumAlignment, bytes); + return allocate(mutation, MinimumAlignment, bytes, false); } void GuestHeapFree_nid_postfix(void* pointer) { @@ -242,7 +242,7 @@ void* GuestHeapReallocate_nid_postfix(void* pointer, std::size_t bytes) { free(mutation, pointer); return nullptr; } - void* result = allocate(mutation, MinimumAlignment, bytes); + void* result = allocate(mutation, MinimumAlignment, bytes, range.gpu); std::memcpy(result, pointer, std::min(bytes, range.bytes)); free(mutation, pointer); return result; @@ -257,7 +257,7 @@ void* GuestHeapRealign_nid_postfix(void* pointer, std::size_t bytes, std::size_t free(mutation, pointer); return nullptr; } - void* result = allocate(mutation, alignment, bytes); + void* result = allocate(mutation, alignment, bytes, range.gpu); std::memcpy(result, pointer, std::min(bytes, range.bytes)); free(mutation, pointer); return result; @@ -271,7 +271,12 @@ std::size_t GuestHeapUsableSize_nid_postfix(const void* pointer) { void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes) { GuestAllocations::Mutation mutation; - return allocate(mutation, alignment, bytes); + return allocate(mutation, alignment, bytes, false); +} + +void* GuestHeapAlignForGpu_nid_postfix(std::size_t alignment, std::size_t bytes) { + GuestAllocations::Mutation mutation; + return allocate(mutation, alignment, bytes, true); } }