Skip to content
Merged
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
8 changes: 4 additions & 4 deletions core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ int VulkanDevice::WriteLabelOnGpu(std::uint64_t address, std::span<const std::by
// pair for a whole group of labels recorded back to back (Recorder::RecordStore orders the
// stores of a run against each other and against the work before and after, the queued DCC
// key stores included).
const auto recordStore = [&] { recorder.RecordStore(import->buffer, address - import->base, bytes, address); };
const auto recordStore = [&] { recorder.RecordStore(import->buffer, Graphics::HostImportOffset(*import, address), bytes, address); };
// Only a write-back that can land over these bytes (a listed copied writer of the range, as
// FillBuffer tests) puts the label behind the completions; any other pending completion
// stores elsewhere. Debug aid: APS5_LABEL_GATE_ALL=1 gates on any completion, as before (a
Expand Down Expand Up @@ -2387,7 +2387,7 @@ bool VulkanDevice::FillBuffer(std::uint64_t address, std::size_t bytes, std::spa
Graphics::RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
Graphics::Recorder::CountBarriers(CommandClass::Fill);
}
const auto offset = address - import->base;
const auto offset = Graphics::HostImportOffset(*import, address);
if (uniform) {
++uniformFills;
context.Resolved(&Graphics::DeviceFunctions::cmdFillBuffer, "vkCmdFillBuffer")(commands, import->buffer, offset, bytes, pattern[0]);
Expand Down Expand Up @@ -2654,7 +2654,7 @@ VulkanDevice::CopyOutcome VulkanDevice::CopyBuffer(std::uint64_t destination, st
Graphics::Recorder::CountBarriers(CommandClass::Copy);
}
const auto gpuTiming = recorder.BeginGpuTiming(programAddress);
const VkBufferCopy region{source - sourceImport->base, destination - destinationImport->base, bytes};
const VkBufferCopy region{Graphics::HostImportOffset(*sourceImport, source), Graphics::HostImportOffset(*destinationImport, destination), bytes};
context.Resolved(&Graphics::DeviceFunctions::cmdCopyBuffer, "vkCmdCopyBuffer")(commands, sourceImport->buffer, destinationImport->buffer, 1, &region);
recorder.EndGpuTiming(gpuTiming, bytes);
// The copied bytes are visible to everything recorded after and to the host, as after a fill.
Expand Down Expand Up @@ -4486,7 +4486,7 @@ void VulkanDevice::recordDispatch(RecordedDispatch& record) {
const auto gpuTiming = recorder.BeginGpuTiming(record.programAddress != 0 ? record.programAddress : record.shader->program->variantId);
if (state->checkpointMarker != nullptr) state->checkpointMarker(commands, reinterpret_cast<const void*>(static_cast<std::uintptr_t>(record.programAddress)));
if (argumentImport != nullptr) {
context.Resolved(&Graphics::DeviceFunctions::cmdDispatchIndirect, "vkCmdDispatchIndirect")(commands, argumentImport->buffer, arguments - argumentImport->base);
context.Resolved(&Graphics::DeviceFunctions::cmdDispatchIndirect, "vkCmdDispatchIndirect")(commands, argumentImport->buffer, Graphics::HostImportOffset(*argumentImport, arguments));
} else {
const auto* limit = state->properties.limits.maxComputeWorkGroupCount;
if (record.x <= limit[0] && record.y <= limit[1] && record.z <= limit[2]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ struct HostImport {
bool joined = false;
std::shared_ptr<void> chunk;
mutable std::uint64_t lastUse = 0;
std::uint64_t lead = 0;
};

inline VkDeviceSize HostImportOffset(const HostImport& import, std::uint64_t address) {
return address - import.base + import.lead;
}

enum class ImportWatch : std::uint8_t { Watch, Unwatch };

struct ImportProbe {
Expand All @@ -63,8 +68,8 @@ ImportWatch PrepareImportWatch(const Context& context);
void SetImportWatch(const Context& context, ImportWatch watch);

// The host import of the registered allocation containing [address, address + bytes), made on demand
// (alignment and budget permitting), or null. Bytes at `address` are at `address - import->base` in
// the import's buffer.
// (alignment and budget permitting), or null. Bytes at `address` are at `HostImportOffset(*import,
// address)` in the import's buffer.
const HostImport* HostImportFor(const Context& context, std::uint64_t address, std::size_t bytes);
const HostImport* ExistingHostImportFor(const Context& context, std::uint64_t address, std::size_t bytes);
void SetHostImportWindow(std::uint64_t bytes);
Expand Down
2 changes: 1 addition & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/src/DccMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ void TraceKeyStore(const char* path, std::uint64_t begin, std::size_t count) {
bool StoreUncompressedOnGpu(const Context& context, Recorder& recorder, std::uint64_t begin, std::size_t count) {
const auto* import = HostImportFor(context, begin, count);
if (import == nullptr) return false;
const VkDeviceSize first = begin - import->base;
const VkDeviceSize first = HostImportOffset(*import, begin);
const VkDeviceSize last = first + count;
const VkDeviceSize fillBegin = std::min((first + 3) & ~VkDeviceSize{3}, last);
const VkDeviceSize fillEnd = std::max(last & ~VkDeviceSize{3}, fillBegin);
Expand Down
16 changes: 8 additions & 8 deletions core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ void recordCmaskClear(const Context& context, Recorder& recorder, const HostImpo
recorder.FlushKeyStoresOverlapping(address, bytes);
const auto commands = recorder.Commands();
recorder.Keep(resident);
context.detiler->DispatchCmaskClear(commands, import.buffer, address - import.base, bytes, view, color.extent.width, color.extent.height, color.elementBytes, color.clearWords, color.dccAddress == 0);
context.detiler->DispatchCmaskClear(commands, import.buffer, HostImportOffset(import, address), bytes, view, color.extent.width, color.extent.height, color.elementBytes, color.clearWords, color.dccAddress == 0);
recorder.NotePendingWrite(address, bytes);
proveCmask(address, bytes, GuestMemory::MarkWritten(address, bytes));
}
Expand Down Expand Up @@ -950,7 +950,7 @@ const HostImport* InPlaceDrawInput(const Context& context, std::uint64_t address
const auto drawWriters = DrawCopiedWriters();
if (std::any_of(drawWriters->begin(), drawWriters->end(), overlaps)) return nullptr;
const auto* import = HostImportFor(context, address, bytes);
if (import == nullptr || (address - import->base) % alignment != 0) return nullptr;
if (import == nullptr || HostImportOffset(*import, address) % alignment != 0) return nullptr;
recorder->NotePendingRead(address, bytes, Recorder::ReadKind::DrawInput);
if (behindGpuWrite != nullptr && behind) *behindGpuWrite = true;
return import;
Expand Down Expand Up @@ -1132,7 +1132,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
}
if (import != nullptr) {
inputs.indexHandle = import->buffer;
inputs.indexOffset = draw.indexAddress - import->base;
inputs.indexOffset = HostImportOffset(*import, draw.indexAddress);
inputs.inPlaceReads.emplace_back(draw.indexAddress, draw.indexAddress + indexBytes);
} else {
inputs.indices = std::move(copy.buffer);
Expand Down Expand Up @@ -1201,7 +1201,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
RequireNoMultisampleTarget(begin, bytes, "a vertex buffer read");
if (const auto* import = InPlaceDrawInput(context, begin, bytes, plan.alignments[range], &inputs.vertexInputBehindGpuWrite)) {
rangeHandles.push_back(import->buffer);
rangeOffsets.push_back(begin - import->base);
rangeOffsets.push_back(HostImportOffset(*import, begin));
inputs.inPlaceReads.emplace_back(begin, end);
continue;
}
Expand Down Expand Up @@ -1367,8 +1367,8 @@ void recordDrawCommands(const Context& context, VkCommandBuffer commands, const
else context.Resolved(&DeviceFunctions::cmdDraw, "vkCmdDraw")(commands, draw.indexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance);
} else if (indirect->path == IndirectDrawPath::Gpu) {
if (args->countIndirect) {
if (draw.indexed) context.Function<PFN_vkCmdDrawIndexedIndirectCountKHR>("vkCmdDrawIndexedIndirectCountKHR")(commands, argumentBuffer, argumentOffset, indirect->countImport->buffer, args->countAddress - indirect->countImport->base, args->count, args->stride);
else context.Function<PFN_vkCmdDrawIndirectCountKHR>("vkCmdDrawIndirectCountKHR")(commands, argumentBuffer, argumentOffset, indirect->countImport->buffer, args->countAddress - indirect->countImport->base, args->count, args->stride);
if (draw.indexed) context.Function<PFN_vkCmdDrawIndexedIndirectCountKHR>("vkCmdDrawIndexedIndirectCountKHR")(commands, argumentBuffer, argumentOffset, indirect->countImport->buffer, HostImportOffset(*indirect->countImport, args->countAddress), args->count, args->stride);
else context.Function<PFN_vkCmdDrawIndirectCountKHR>("vkCmdDrawIndirectCountKHR")(commands, argumentBuffer, argumentOffset, indirect->countImport->buffer, HostImportOffset(*indirect->countImport, args->countAddress), args->count, args->stride);
} else if (args->count <= 1 || context.multiDrawIndirect) {
if (draw.indexed) context.Resolved(&DeviceFunctions::cmdDrawIndexedIndirect, "vkCmdDrawIndexedIndirect")(commands, argumentBuffer, argumentOffset, args->count, args->stride);
else context.Resolved(&DeviceFunctions::cmdDrawIndirect, "vkCmdDrawIndirect")(commands, argumentBuffer, argumentOffset, args->count, args->stride);
Expand Down Expand Up @@ -1416,7 +1416,7 @@ bool recordIndirectArguments(const Context& context, VkCommandBuffer commands, R
if (args->countIndirect) recorder->NotePendingRead(args->countAddress, 4, Recorder::ReadKind::Indirect);
}
argumentBuffer = indirect.argumentImport->buffer;
argumentOffset = args->arguments - indirect.argumentImport->base;
argumentOffset = HostImportOffset(*indirect.argumentImport, args->arguments);
const bool rewritten = args->vertexRule == Rule::Constant || args->instanceRule == Rule::Constant;
if (!rewritten) return false;
const auto bytes = static_cast<std::size_t>(args->RangeBytes());
Expand Down Expand Up @@ -1699,7 +1699,7 @@ void captureInputs(const Context& context, Recorder& recorder, VkCommandBuffer c
}
const auto* imported = HostImportFor(context, begin, bytes);
Require(imported != nullptr, "capture input has no host import");
addSample(begin, bytes, imported->buffer, begin - imported->base, reinterpret_cast<const std::byte*>(begin));
addSample(begin, bytes, imported->buffer, HostImportOffset(*imported, begin), reinterpret_cast<const std::byte*>(begin));
}
CaptureTrace::Log("input-capture draw=%llu batch=%llu target=%llx ranges=%zu bytes=%zu", draw, batch, static_cast<unsigned long long>(target), samples.size(), total);
if (samples.empty()) return;
Expand Down
16 changes: 10 additions & 6 deletions core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ const char* createDmaBufImport(const Context& context, HostImport& entry, int fi
#ifndef _WIN32
constexpr std::uint64_t ImportChunkBytes = std::uint64_t{64} << 20u;
constexpr VkBufferUsageFlags ChunkImportUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
constexpr std::uint64_t SparseBlockBytes = 65536;

struct ImportChunk {
VkDevice device = VK_NULL_HANDLE;
Expand Down Expand Up @@ -559,13 +560,15 @@ VkMemoryRequirements dmaBufBufferRequirements(const Context& context, const Host
}

bool createSparseDmaBufImport(const Context& context, HostImport& entry, int file, std::uint64_t offset) {
const auto lead = offset % SparseBlockBytes;
offset -= lead;
const bool ownQueue = context.sparseQueue != VK_NULL_HANDLE && context.sparseQueueMutex != nullptr;
if (!context.sparseBinding || entry.bytes <= ImportChunkBytes || (!ownQueue && !GuestMemory::GpuMutex().HeldByThisThread()) || udmabufDevice() < 0) return false;
struct stat backing {};
if (fstat(file, &backing) != 0) throwSparseImport(entry, "fstat of the shared backing", VK_ERROR_INVALID_EXTERNAL_HANDLE);
const auto chunkTypes = dmaBufBufferRequirements(context, entry, 0, ChunkImportUsage, ImportChunkBytes, nullptr).memoryTypeBits;
VkBuffer buffer = VK_NULL_HANDLE;
const auto requirements = dmaBufBufferRequirements(context, entry, VK_BUFFER_CREATE_SPARSE_BINDING_BIT, SparseImportUsage, entry.bytes, &buffer);
const auto requirements = dmaBufBufferRequirements(context, entry, VK_BUFFER_CREATE_SPARSE_BINDING_BIT, SparseImportUsage, lead + entry.bytes, &buffer);
const auto alignment = requirements.alignment;
const bool chosen = alignment != 0 && offset % alignment == 0 && ImportChunkBytes % alignment == 0 && (chunkTypes & ~requirements.memoryTypeBits) == 0 && (requirements.memoryTypeBits & chunkTypes) != 0 &&
(offset + requirements.size + ImportChunkBytes - 1) / ImportChunkBytes * ImportChunkBytes <= static_cast<std::uint64_t>(backing.st_size);
Expand Down Expand Up @@ -616,9 +619,10 @@ bool createSparseDmaBufImport(const Context& context, HostImport& entry, int fil
if (address == 0) fail("vkGetBufferDeviceAddressKHR", VK_ERROR_UNKNOWN);
entry.buffer = buffer;
entry.memory = VK_NULL_HANDLE;
entry.address = address;
entry.address = address + lead;
entry.chunk = std::move(chunks);
entry.dmaBuf = true;
entry.lead = lead;
return true;
}
#endif
Expand Down Expand Up @@ -3556,7 +3560,7 @@ void GuestBufferMemory::UploadPrepare(bool addressable) {
// device-local buffer that the CPU fallback replaces (none without a recorder to
// record the copies: UploadFinish then binds the region in place).
bool staged = Recorder::Active() != nullptr && stagingEligible(region, addressable);
const bool misaligned = !bindableInPlace(region.begin - entry->base, addressable);
const bool misaligned = !bindableInPlace(HostImportOffset(*entry, region.begin), addressable);
if (staged) {
const auto allocateStart = std::chrono::steady_clock::now();
region.buffer = stagingBuffer(context, static_cast<std::size_t>(region.end - region.begin), gpuCopyUsage(addressable));
Expand Down Expand Up @@ -3760,7 +3764,7 @@ void GuestBufferMemory::UploadFinish(bool addressable) {
// A staged region (see stagingEligible) is copied out of the import even when aligned;
// without a recorder to record the copies it binds in place like any other.
const bool staged = recorder != nullptr && stagingEligible(region, addressable);
if (entry != nullptr && !staged && bindableInPlace(region.begin - entry->base, addressable)) {
if (entry != nullptr && !staged && bindableInPlace(HostImportOffset(*entry, region.begin), addressable)) {
region.direct = entry;
region.runCut = runImport;
region.snapshot.clear();
Expand All @@ -3776,7 +3780,7 @@ void GuestBufferMemory::UploadFinish(bool addressable) {
copyOnGpu = true;
region.deviceLocal = staged;
region.copySource = entry->buffer;
region.copySourceBase = entry->base;
region.copySourceBase = entry->base - entry->lead;
}
}
if (region.direct != nullptr) {
Expand Down Expand Up @@ -4104,7 +4108,7 @@ VkDescriptorBufferInfo GuestBufferMemory::Descriptor(std::uint64_t address, std:
return std::string(text);
};
if (!(address >= region.begin && address + bytes <= region.end && (region.buffer != nullptr || region.direct != nullptr || region.mirror != nullptr))) Require(false, describe("exceeds"));
const auto base = region.direct != nullptr ? region.direct->base : region.mirror != nullptr ? region.mirror->base : region.begin;
const auto base = region.direct != nullptr ? region.direct->base - region.direct->lead : region.mirror != nullptr ? region.mirror->base : region.begin;
const auto offset = address - base;
Require(context.limits.minStorageBufferOffsetAlignment != 0, "no storage buffer offset alignment");
Require(base % 4 == 0, "a guest buffer view in a GPU owner that does not start at a DWORD boundary is not implemented");
Expand Down
10 changes: 5 additions & 5 deletions core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2312,7 +2312,7 @@ void StorageTexture::upload(const std::vector<bool>* layers) {
batch = std::make_unique<CommandBatch>(context);
commands = batch->Handle();
}
const auto importOffset = descriptor.baseAddress - import->base;
const auto importOffset = HostImportOffset(*import, descriptor.baseAddress);
if (direct) {
recordDirectUploadBarrier(commands, layers == nullptr);
for (std::uint32_t layer = 0; layer < arrayLayers; ++layer) {
Expand Down Expand Up @@ -2738,7 +2738,7 @@ std::uint64_t StorageTexture::uploadWindows(const HostImport& import, std::span<
batch = std::make_unique<CommandBatch>(context);
commands = batch->Handle();
}
const auto importOffset = descriptor.baseAddress - import.base;
const auto importOffset = HostImportOffset(import, descriptor.baseAddress);
if (direct) {
recordDirectUploadBarrier(commands, discard);
for (const auto& window : windows) {
Expand Down Expand Up @@ -2871,7 +2871,7 @@ std::uint64_t StorageTexture::writeBackWindows(std::span<const ImportSegment> se
if (!shadowed.empty() && shadowed.back().end == guestBegin && shadowed.back().slab == destination->slab) shadowed.back().end = pieceEnd;
else shadowed.push_back({guestBegin, pieceEnd, destination->slab});
} else {
importCopies[segment].push_back({scratchOffset, guestBegin - import.base, pieceEnd - guestBegin});
importCopies[segment].push_back({scratchOffset, HostImportOffset(import, guestBegin), pieceEnd - guestBegin});
if (!imported.empty() && imported.back().second == guestBegin) imported.back().second = pieceEnd;
else imported.emplace_back(guestBegin, pieceEnd);
}
Expand Down Expand Up @@ -2966,7 +2966,7 @@ std::uint64_t StorageTexture::writeBackWindows(std::span<const ImportSegment> se
}
for (const auto& [begin, end, slab, import] : seeds) {
// The piece's own slab (a seeded unit is one the piece covers partly).
const VkBufferCopy seed{begin - import->base, SlabOffset(*import, *slab, begin), end - begin};
const VkBufferCopy seed{HostImportOffset(*import, begin), SlabOffset(*import, *slab, begin), end - begin};
context.Resolved(&DeviceFunctions::cmdCopyBuffer, "vkCmdCopyBuffer")(commands, import->buffer, slab->buffer, 1, &seed);
NoteShadowSeed(begin, end);
}
Expand Down Expand Up @@ -4779,7 +4779,7 @@ void StorageTexture::writeBackLayers(const std::vector<bool>& layers) {
for (const auto& [from, to] : keep) {
const auto begin = std::max(from, segment.begin);
const auto end = std::min(to, segment.end);
if (begin < end) copies.push_back({begin - descriptor.baseAddress, begin - segment.import->base, end - begin});
if (begin < end) copies.push_back({begin - descriptor.baseAddress, HostImportOffset(*segment.import, begin), end - begin});
}
if (!copies.empty()) context.Function<PFN_vkCmdCopyBuffer>("vkCmdCopyBuffer")(commands, tiledScratch->Handle(), segment.import->buffer, static_cast<std::uint32_t>(copies.size()), copies.data());
}
Expand Down
Loading
Loading