mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
Merge pull request #1189 from MichonGoddijn231849/fix/cb-resolve-tiled-targets
fix(agc): CB resolve into any tiled color target
This commit is contained in:
4 files changed
+121
-2
No files matched your search
@@ -1117,12 +1117,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
|
||||
|
||||
@@ -2671,7 +2671,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));
|
||||
|
||||
@@ -2610,6 +2610,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;
|
||||
|
||||
@@ -6435,6 +6435,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()) {
|
||||
@@ -7879,6 +7976,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";
|
||||
@@ -8044,6 +8150,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);
|
||||
|
||||
Reference in new issue
Block a user