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
21 changes: 8 additions & 13 deletions core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1963,20 +1963,15 @@ VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target,
const bool created = surface == nullptr;
GuestAllocations::Lease creationLease;
if (created) {
for (const auto& surface : surfaces()) {
if (!surface->active->load(std::memory_order_acquire) || !surface->samplingActive || surface->context.device != context.device) continue;
const auto bytes = target.samples == 1u ? DepthSliceBytes(target.extent, target.format == VK_FORMAT_D16_UNORM ? 2u : 4u) : MultisampledDepthBytes_nid_no_patch(target.extent, target.format == VK_FORMAT_D16_UNORM ? 2u : 4u, target.samples);
Require(target.address <= std::numeric_limits<std::uint64_t>::max() - bytes && target.htileAddress <= std::numeric_limits<std::uint64_t>::max() - HtileMetadataBytes(target.extent), "native depth attachment range overflows");
for (const auto& range : surface->sampling.initial) {
Require(target.address >= range.address + range.bytes || range.address >= target.address + bytes, "native multisample depth attachment layout or metadata changed");
if (target.stencilAddress != 0u) {
const auto stencilBytes = target.samples == 1u ? DepthSliceBytes(target.extent, 1u) : MultisampledDepthBytes_nid_no_patch(target.extent, 1u, target.samples);
Require(target.stencilAddress <= std::numeric_limits<std::uint64_t>::max() - stencilBytes && (target.stencilAddress >= range.address + range.bytes || range.address >= target.stencilAddress + stencilBytes), "native multisample stencil attachment aliases a resident depth surface");
}
if (target.htileAddress != 0u) Require(target.htileAddress >= range.address + range.bytes || range.address >= target.htileAddress + HtileMetadataBytes(target.extent), "native multisample depth attachment layout or metadata changed");
}
}
const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT;
const auto depthBytes = target.samples == 1u ? DepthSliceBytes(target.extent, d16 ? 2u : 4u) : MultisampledDepthBytes_nid_no_patch(target.extent, d16 ? 2u : 4u, target.samples);
const auto stencilBytes = target.stencilAddress == 0u ? 0u : target.samples == 1u ? DepthSliceBytes(target.extent, 1u) : MultisampledDepthBytes_nid_no_patch(target.extent, 1u, target.samples);
const auto metadataBytes = target.htileAddress == 0u ? 0u : HtileMetadataBytes(target.extent);
Require(target.address <= std::numeric_limits<std::uint64_t>::max() - depthBytes && target.stencilAddress <= std::numeric_limits<std::uint64_t>::max() - stencilBytes && target.htileAddress <= std::numeric_limits<std::uint64_t>::max() - metadataBytes, "native depth attachment range overflows");
lock.unlock();
RequireNoResidentDepthRead_nid_no_patch(target.address, static_cast<std::size_t>(depthBytes));
if (stencilBytes != 0u) RequireNoResidentDepthRead_nid_no_patch(target.stencilAddress, static_cast<std::size_t>(stencilBytes));
if (metadataBytes != 0u) RequireNoResidentDepthRead_nid_no_patch(target.htileAddress, static_cast<std::size_t>(metadataBytes));
auto sampling = target.samples == 1u ? DepthSamplingState{} : prepareDepthSampling(context, target);
creationLease = target.samples == 1u || !sampling.refusal.empty() ? GuestAllocations::Lease{} : GuestAllocations::GuestAllocationsAcquireAll_nid_postfix();
lock.lock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,39 @@ void CheckDrawFeedback() {
std::puts("Native depth feedback refused through the draw resource path; a written surface refused and a depth-tested one retired on guest read");
}

void CheckDepthAttachmentAlias() {
const auto device = OpenVulkanTestDevice();
Require(device != nullptr, "native depth attachment alias requires Vulkan");
const auto context = device->graphicsContext();
constexpr VkExtent2D extent{5u, 3u};
constexpr std::uint32_t samples = 4u;
const auto bytes = static_cast<std::size_t>(MultisampledDepthBytes_nid_no_patch(extent, 4u, samples));
TargetMemory memory(bytes), firstMetadata(65536u), secondMetadata(65536u);
std::memset(memory.Data(), 0x3c, bytes);
std::memset(firstMetadata.Data(), 0, 65536u);
std::memset(secondMetadata.Data(), 0, 65536u);
struct Cleanup {
AgcDriver::VulkanDevice& device;
~Cleanup() { device.WaitIdle(); ClearCachedTextures(device.Device()); ClearDepthSurfaces(device.Device()); }
} cleanup{*device};
DepthTarget first{memory.Address(), 0u, extent, VK_FORMAT_D32_SFLOAT, 0.0f, 0u, firstMetadata.Address(), false, samples};
first.depthSwizzle = 24u;
first.iterate256 = first.htilePipeAligned = first.htileDepthOnly = true;
const auto firstView = DepthSurfaceView(context, first);
const auto words = DepthSampleWords(first);
auto kept = DepthSurfaceTexture(context, words, DecodeTextureResource(words), VkComponentMapping{});
Require(kept != nullptr, "attachment alias fixture has no held native depth view");
auto second = first;
second.extent.width = 6u;
second.htileAddress = secondMetadata.Address();
Require(MultisampledDepthBytes_nid_no_patch(second.extent, 4u, samples) <= bytes, "attachment alias fixture exceeds its backing");
const auto secondView = DepthSurfaceView(context, second);
Require(secondView != VK_NULL_HANDLE && secondView != firstView, "an aliased depth attachment reused the previous layout's view");
Require(DepthSurfaceView(context, second) == secondView, "an unchanged native depth attachment was not reused");
for (std::size_t offset = 0u; offset < bytes; ++offset) Require(memory.Data()[offset] == std::byte{0x3c}, "retiring an unwritten attachment alias changed guest bytes");
std::puts("native depth attachment alias changes layout while retaining held GPU views");
}

enum class ClearFault { None, PartialStore, CpuWrite, DepthWrite, BadMetadata, UnprovenDispatch, PendingWrite, Overlap, PossibleStore, CompletedPossibleStore, DriverDispatch, ImportWindowWrite };

void CheckClearDispatch() {
Expand Down Expand Up @@ -927,10 +960,10 @@ void CheckDepthTarget(Context context, VkFormat format, std::uint32_t fragments,
Require(probe[0] == std::byte{0xa5}, "resident depth guard blocked an unrelated read");
auto alias = target;
alias.htileAddress += 65536u;
TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed");
TargetRefuses([&] { DepthSurfaceView(context, alias); }, "sample-preserving guest publication");
alias = target;
alias.htileDepthOnly = !target.htileDepthOnly;
TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed");
TargetRefuses([&] { DepthSurfaceView(context, alias); }, "sample-preserving guest publication");
auto resource = DecodeTextureResource(words);
for (std::uint32_t field = 0u; field < 18u; ++field) {
auto changed = resource;
Expand Down Expand Up @@ -1042,7 +1075,7 @@ void CheckHtileRouting(Context context, VkFormat format, std::uint32_t fragments
auto alias = target;
alias.samples = 1u;
alias.address = single.Address();
TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed");
Require(DepthSurfaceView(context, alias) != VK_NULL_HANDLE, "a single-sample bind could not retire an unwritten native HTILE owner");
Require(untouched(), "a single-sample bind over a native owner's HTILE stored expanded words into it");
std::printf("Native depth format=%u samples=%u: binds over the owner's HTILE left its words alone\n", static_cast<std::uint32_t>(format), fragments);
}
Expand Down Expand Up @@ -1304,6 +1337,7 @@ int main(int argc, char** argv) {
}
CheckDrawFeedback();
const auto context = device->GetContext();
if (argc == 1) CheckDepthAttachmentAlias();
std::unique_lock lock(AgcDriver::GuestMemory::GpuMutex());
Require(DepthSupported(context, VK_FORMAT_D32_SFLOAT, 4u), "the native depth regression requires sampled D32 with four samples");
if (argc == 2 && std::string_view(argv[1]) == "--clear-refusals") {
Expand Down
Loading