Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,23 @@ bool sameRange(const HostImport& entry, const GuestAllocations::Lease& lease) {
return sameRun(entry, entry.joined ? joinedRun(lease, entry.base, entry.base + entry.bytes) : importRun(lease, entry.base));
}

bool singleRangeImportCurrent(const HostImport& entry) {
if (entry.joined || entry.unwatched || entry.ranges.size() != 1) return false;
const auto generation = GuestAllocations::GuestAllocationsGeneration_nid_postfix();
const auto current = GuestAllocations::GuestAllocationsLookup_nid_postfix(entry.base, false);
if (current == nullptr || !current->readable || entry.ranges.front().owner_before(current) || current.owner_before(entry.ranges.front())) return false;
if (entry.base < current->address || entry.bytes > current->bytes || entry.base - current->address > current->bytes - entry.bytes) return false;
if (entry.bytes == current->bytes) {
if (current->address != 0) {
const auto previous = GuestAllocations::GuestAllocationsLookup_nid_postfix(current->address - 1, false);
if (previous != nullptr && continuesRun(*previous, *current)) return false;
}
const auto next = GuestAllocations::GuestAllocationsLookup_nid_postfix(current->address + current->bytes, false);
if (next != nullptr && continuesRun(*current, *next)) return false;
}
return generation == GuestAllocations::GuestAllocationsGeneration_nid_postfix();
}

bool pointerHeld(const HostImports& state, const HostImport& entry) {
return entry.lastUse >= state.buildFloor;
}
Expand Down Expand Up @@ -4613,7 +4630,12 @@ std::uint64_t HostImportSerial(const Context& context, std::uint64_t address, st
std::lock_guard lock(state.mutex);
// An import whose registered range changed must not be reused: reconcile first, as an upload
// does (the walk only runs when the registry changed since the last one).
if (reconcile && GuestAllocations::GuestAllocationsGeneration_nid_postfix() != state.refreshedGeneration) static_cast<void>(refreshImports(context, state, GuestAllocations::GuestAllocationsAcquire_nid_postfix()));
if (reconcile && GuestAllocations::GuestAllocationsGeneration_nid_postfix() != state.refreshedGeneration) {
const auto next = state.imports.upper_bound(address);
const auto existing = next != state.imports.begin() ? &std::prev(next)->second : nullptr;
const bool current = state.device == context.device && existing != nullptr && address >= existing->base && address + bytes <= existing->base + existing->bytes && singleRangeImportCurrent(*existing);
if (!current) refreshImports(context, state, GuestAllocations::GuestAllocationsAcquire_nid_postfix());
}
auto found = state.imports.upper_bound(address);
if (found == state.imports.begin()) return 0;
--found;
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1770,6 +1770,7 @@ void secondMappingImportTests(const Device& device) {
const auto first = HostImportSerial(context, address, bytes, true);
Require(first != 0 && HostImportSerial(context, address, bytes, true) == first, "singly mapped direct memory lost its import");
Require(sceKernelMapDirectMemory(&release.alias, page, 0x33, 0, release.physical, page) == 0, "map the first page a second time");
Require(HostImportSerial(context, address, bytes, true) != first, "a second mapping kept a stale import serial before the next import lookup");
Require(HostImportFor(context, address, bytes) != nullptr, "direct memory was not imported again after a second mapping of its first page");
const auto second = HostImportSerial(context, address, bytes, true);
Require(second != 0 && second != first, "the import of direct memory whose pages were replaced was kept");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
#include <mutex>
#include <string>

namespace AgcDriver {

struct VulkanDeviceTestAccess {
static Graphics::Context ContextOf(const VulkanDevice& device) { return device.graphicsContext(); }
};

}

namespace {

namespace Graphics = AgcDriver::Graphics;
Expand Down Expand Up @@ -74,10 +82,7 @@ class GuestBlock {
enum class Outcome : std::uint8_t { NoDevice, NoImport, Passed };

Graphics::Context Probe(const AgcDriver::VulkanDevice& device) {
Graphics::Context probe{};
probe.device = device.Device();
probe.hostImportAlignment = 1;
return probe;
return AgcDriver::VulkanDeviceTestAccess::ContextOf(device);
}

bool Fill(AgcDriver::VulkanDevice& device, std::uint64_t address) {
Expand Down Expand Up @@ -113,11 +118,13 @@ Outcome WindowsFollowTheirRange() {
Require(first != 0, "host import windows: the window at " + Hex(address) + " has no serial");

GuestBlock other(OtherBytes);
Require(Graphics::HostImportSerial(probe, address, ProbeBytes, true) == first, "host import windows: an unrelated mapping changed the import serial");
Require(Fill(*device, address), "host import windows: the window at " + Hex(address) + " cannot be filled after an unrelated registration");
Require(Graphics::HostImportSerial(probe, address, ProbeBytes, false) == first, "host import windows: the window at " + Hex(address) + " was dropped by an unrelated registration, although its range still owns it");

GuestAllocations::Mutation().Remove(guest.Data());
GuestAllocations::Mutation().Add(guest.Data(), BlockBytes, true, true, true);
Require(Graphics::HostImportSerial(probe, address, ProbeBytes, true) != first, "host import windows: a remapped range kept its stale import serial before the next fill");
Require(Fill(*device, address), "host import windows: the window at " + Hex(address) + " cannot be filled after its range was mapped again");
const auto second = Graphics::HostImportSerial(probe, address, ProbeBytes, false);
Require(second != 0 && second != first, "host import windows: the window of the range mapped again kept the serial " + Hex(first));
Expand Down
Loading