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
4 changes: 3 additions & 1 deletion core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1110,12 +1110,14 @@ if(BUILD_TESTING)
add_test(NAME agc_resident_present COMMAND agc_driver_recorder_tests --resident-present-only)
set_tests_properties(agc_resident_present PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME agc_queued_write_groups COMMAND agc_driver_recorder_tests --queued-write-groups-only)
add_test(NAME agc_tiled_resolve COMMAND agc_driver_recorder_tests --tiled-resolve-only)
set_tests_properties(agc_tiled_resolve PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME agc_slice_dirty COMMAND agc_driver_recorder_tests --slice-dirty-only)
set_tests_properties(agc_slice_dirty PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME agc_metadata_pass COMMAND agc_driver_recorder_tests --metadata-pass-only)
set_tests_properties(agc_metadata_pass PROPERTIES SKIP_RETURN_CODE 77)
if(WIN32)
set_tests_properties(agc_recorder_read_list agc_host_import_unmap agc_parked_import_unmap agc_host_import_retirement agc_sparse_run_import agc_sparse_run_import_copied agc_unit_shadow agc_descriptor_pool_recycling agc_draw_snapshot_cap agc_draw_snapshot_epoch agc_multisample_guest_access agc_draw_inputs_in_place agc_resident_present agc_slice_dirty agc_queued_write_groups agc_metadata_pass PROPERTIES ENVIRONMENT_MODIFICATION
set_tests_properties(agc_recorder_read_list agc_host_import_unmap agc_parked_import_unmap agc_host_import_retirement agc_sparse_run_import agc_sparse_run_import_copied agc_unit_shadow agc_descriptor_pool_recycling agc_draw_snapshot_cap agc_draw_snapshot_epoch agc_multisample_guest_access agc_draw_inputs_in_place agc_resident_present agc_slice_dirty agc_queued_write_groups agc_metadata_pass agc_tiled_resolve PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
add_test(NAME agc_host_import_second_mapping COMMAND agc_driver_recorder_tests --host-import-second-mapping-only)
set_tests_properties(agc_host_import_second_mapping PROPERTIES SKIP_RETURN_CODE 77 ENVIRONMENT_MODIFICATION
Expand Down
2 changes: 1 addition & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2670,7 +2670,7 @@ void RunColorMetadataPass(const Context& context, const ColorMetadataPass& pass)
if (pass.mode == ColorMetadataPass::Mode::Resolve) {
Require(pass.source.has_value() && pass.targets.size() == 1, "CB resolve without its source and destination");
const auto& destination = pass.targets.front();
Require(destination.tileMode == ColorTileMode::RenderTarget && context.detiler != nullptr, "CB resolve into a target without a resident image is not implemented");
Require(destination.tileMode != ColorTileMode::Linear && context.detiler != nullptr, "CB resolve into a target without a resident image is not implemented");
const auto resident = CachedStorageSurface(context, SurfaceForTarget(destination));
Require(resident->Attachable(), "storage format cannot be a color attachment");
ResolveMultisampleTarget(context, *pass.source, *resident, resident->AttachmentView(destination.format, destination.mip));
Expand Down
10 changes: 10 additions & 0 deletions core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2522,6 +2522,16 @@ void multisampleTests() {
for (std::uint32_t pixel = 0; pixel < 4; ++pixel) queue.context[0x2fe + pixel * 4u] = 0x622ae6aeu;
expectFailure([&] { DecodeColorMetadataPass(queue); }, "differs from the rasterizer's");
queue = rasterizedResolve;
std::vector<std::byte> resolvedBlock(2u * 65536u);
const auto resolvedAddress = (reinterpret_cast<std::uintptr_t>(resolvedBlock.data()) + 65535u) / 65536u * 65536u;
for (const auto mode : {AgcDriver::Graphics::ColorTileMode::Standard4KB, AgcDriver::Graphics::ColorTileMode::Standard64KB, AgcDriver::Graphics::ColorTileMode::RenderTarget}) {
auto tiled = queue;
tiled.context[0x327] = static_cast<std::uint32_t>(resolvedAddress >> 8u);
tiled.context[0x391] = static_cast<std::uint32_t>(resolvedAddress >> 40u);
tiled.context[0x3b9] = (tiled.context[0x3b9] & ~(0x1fu << 14u)) | (static_cast<std::uint32_t>(mode) << 14u);
const auto tiledPass = DecodeColorMetadataPass(tiled);
Require(tiledPass.has_value() && tiledPass->mode == ColorMetadataPass::Mode::Resolve && tiledPass->targets.size() == 1 && tiledPass->targets[0].tileMode == mode && tiledPass->targets[0].samples == 1, "a CB resolve into a tile mode " + std::to_string(static_cast<std::uint32_t>(mode)) + " destination did not decode");
}
queue.context[0x32b] = queue.context[0x31c] ^ (1u << 8u);
expectFailure([&] { DecodeColorMetadataPass(queue); }, "different formats or extents");
queue = rasterizedResolve;
Expand Down
107 changes: 107 additions & 0 deletions core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6268,6 +6268,103 @@ void fmaskDecompressMsaaTests(const Device& device, Recorder& recorder) {
std::cout << "FMASK decompress MSAA clear and resolve tests passed\n";
}

void tiledResolveTests(const Device& device, Recorder& recorder) {
namespace GuestMemory = AgcDriver::GuestMemory;
auto context = device.GetContext();
if ((context.limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_4_BIT) == 0 || !device.Graphics()) {
std::cout << "4x color targets or graphics unavailable: CB resolves into tiled targets not tested\n";
return;
}
context.hostImportAlignment = 0;
TextureDetiler detiler(context);
context.detiler = &detiler;
constexpr std::uint32_t side = 128;
constexpr std::size_t targetBytes = side * side * 4u;
constexpr std::size_t sourceBytes = targetBytes * 4u;
constexpr std::size_t bytes = targetBytes + sourceBytes + 65536u;
#ifdef _WIN32
void* block = VirtualAlloc(nullptr, bytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
#else
void* block = std::aligned_alloc(65536, bytes);
#endif
Require(block != nullptr, "cannot allocate the tiled resolve block");
const auto address = reinterpret_cast<std::uint64_t>(block);
{
GuestAllocations::Mutation mutation;
mutation.Add(block, bytes, true, true, true);
}
struct Release {
const Context& context;
void* block;
~Release() {
ClearMultisampleTargets(context.device);
ClearCachedTextures(context.device);
{
GuestAllocations::Mutation mutation;
mutation.Remove(block);
}
#ifdef _WIN32
VirtualFree(block, 0, MEM_RELEASE);
#else
std::free(block);
#endif
}
} release{context, block};
ColorTarget source{};
source.address = address + targetBytes;
source.surfaceAddress = source.address;
source.extent = {side, side};
source.surfaceExtent = source.extent;
source.format = VK_FORMAT_R8G8B8A8_UNORM;
source.bytes = targetBytes;
source.componentMapping = 0xe4u;
source.tileMode = ColorTileMode::RenderTarget;
source.samples = 4;
source.cmaskAddress = address + targetBytes + sourceBytes;
source.cmaskBytes = 4096;
source.cmaskFastClear = true;
const std::array<std::pair<ColorTileMode, std::uint32_t>, 3> modes{{{ColorTileMode::Standard4KB, 0x80402010u}, {ColorTileMode::Standard64KB, 0x10204080u}, {ColorTileMode::RenderTarget, 0x40801020u}}};
for (const auto& [mode, clear] : modes) {
const auto name = std::to_string(static_cast<std::uint32_t>(mode));
std::memset(block, 0x55, targetBytes);
std::memset(static_cast<std::byte*>(block) + targetBytes + sourceBytes, 0, 4096);
ColorTarget destination{};
destination.address = address;
destination.surfaceAddress = address;
destination.extent = {side, side};
destination.surfaceExtent = destination.extent;
destination.format = VK_FORMAT_R8G8B8A8_UNORM;
destination.bytes = targetBytes;
destination.componentMapping = 0xe4u;
destination.tileMode = mode;
source.clearWords = {clear, 0};
RunColorMetadataPass(context, {ColorMetadataPass::Mode::Resolve, {destination}, source});
std::vector<std::uint32_t> resolved(targetBytes / 4);
GuestMemory::Read(address, std::as_writable_bytes(std::span(resolved)));
const auto texels = std::ranges::count(resolved, clear);
Require(texels == static_cast<std::ptrdiff_t>(resolved.size()), "a CB resolve into a tile mode " + name + " target left " + std::to_string(resolved.size() - static_cast<std::size_t>(texels)) + " texels without the resolved color");
recorder.Sync();
ClearMultisampleTargets(context.device);
ClearCachedTextures(context.device);
}
{
ColorTarget destination{};
destination.address = address;
destination.extent = {side, side};
destination.format = VK_FORMAT_R8G8B8A8_UNORM;
destination.bytes = targetBytes;
destination.tileMode = ColorTileMode::Linear;
std::string message;
try {
RunColorMetadataPass(context, {ColorMetadataPass::Mode::Resolve, {destination}, source});
} catch (const std::exception& error) {
message = error.what();
}
Require(message.find("without a resident image is not implemented") != std::string::npos, "a CB resolve into a linear target did not throw: " + message);
}
recorder.Sync();
}

void depthSurfaceProofTests(const Device& device, Recorder& recorder) {
const auto& base = device.GetContext();
if (!device.NullDescriptors()) {
Expand Down Expand Up @@ -7580,6 +7677,15 @@ int main(int argc, char** argv) {
storageUploadLifetimeTests(device, recorder, std::string_view(argv[1]) == "--storage-upload-failure-only");
return 0;
}
if (argc == 2 && std::string_view(argv[1]) == "--tiled-resolve-only") {
if ((device.GetContext().limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_4_BIT) == 0 || !device.Graphics()) {
std::cout << "skipped, the device lacks 4x color targets or a graphics queue\n";
return 77;
}
tiledResolveTests(device, recorder);
std::cout << "CB resolves into tiled targets tests passed\n";
return 0;
}
if (argc == 2 && std::string_view(argv[1]) == "--cube-only") {
singleCubeTests(device, recorder);
std::cout << "Single cube snapshot and storage sampling tests passed\n";
Expand Down Expand Up @@ -7737,6 +7843,7 @@ int main(int argc, char** argv) {
readWrittenStagingTests(device, recorder);
depthSurfaceProofTests(device, recorder);
multisampleGuestAccessTests(device, recorder);
tiledResolveTests(device, recorder);
fmaskDecompressMsaaTests(device, recorder);
misalignedSnapshotTests(device, recorder);
misalignedRegionTests(device, recorder);
Expand Down
Loading