From f2205c2c23b38e4d08207879dfb5146b3d19a576 Mon Sep 17 00:00:00 2001 From: MarcZX100 Date: Wed, 7 Oct 2026 18:29:56 +0000 Subject: [PATCH] test(agc): register BDA cross-range regression --- core/libs/prx/libSceAgcDriver/CMakeLists.txt | 9 +++++ .../prx/libSceAgcDriver/tests/BdaDevice.cpp | 35 ++++++++++++++----- .../libSceAgcDriver/tests/BdaExecution.cpp | 3 +- .../prx/libSceAgcDriver/tests/BdaShader.hpp | 2 +- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index a850b0a9308..4becfb9cba2 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -487,6 +487,15 @@ target_include_directories(agc_driver_bda_device_tests PRIVATE target_link_libraries(agc_driver_bda_device_tests PRIVATE SDL2-static libc shader_recompiler_agc_driver) set_target_properties(agc_driver_bda_device_tests PROPERTIES CXX_EXTENSIONS OFF) configure_windows_unwind(agc_driver_bda_device_tests) +if(BUILD_TESTING) + set_target_properties(agc_driver_bda_device_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_bda_cross_range COMMAND agc_driver_bda_device_tests --cross-range-only) + set_tests_properties(agc_bda_cross_range PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 120) + if(WIN32) + set_tests_properties(agc_bda_cross_range PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() add_test_executable(agc_driver_mesh_tests EXCLUDE_FROM_ALL tests/Mesh.cpp diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp index 484d60a7a47..23f60937c81 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include namespace AgcDriver::Graphics { @@ -19,6 +21,11 @@ namespace { using namespace AgcDriver::Graphics; +class TestUnavailable : public std::runtime_error { +public: + using std::runtime_error::runtime_error; +}; + class Device { public: Device() { @@ -27,10 +34,10 @@ class Device { #else library = SDL_LoadObject("libvulkan.so.1"); #endif - Require(library != nullptr, "cannot load Vulkan"); + if (library == nullptr) throw TestUnavailable("Vulkan loader is unavailable"); try { instanceProc = reinterpret_cast(SDL_LoadFunction(library, "vkGetInstanceProcAddr")); - Require(instanceProc != nullptr, "missing Vulkan instance resolver"); + if (instanceProc == nullptr) throw TestUnavailable("missing Vulkan instance resolver"); VkApplicationInfo application{VK_STRUCTURE_TYPE_APPLICATION_INFO}; application.apiVersion = VK_API_VERSION_1_1; VkInstanceCreateInfo info{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; @@ -39,7 +46,7 @@ class Device { std::uint32_t count = 0; const auto enumerate = function("vkEnumeratePhysicalDevices"); Check(enumerate(instance, &count, nullptr), "vkEnumeratePhysicalDevices"); - Require(count != 0, "no Vulkan device"); + if (count == 0) throw TestUnavailable("no Vulkan device"); std::vector devices(count); Check(enumerate(instance, &count, devices.data()), "vkEnumeratePhysicalDevices"); context.physical = devices.front(); @@ -47,15 +54,21 @@ class Device { Check(extensions(context.physical, nullptr, &count, nullptr), "vkEnumerateDeviceExtensionProperties"); std::vector available(count); Check(extensions(context.physical, nullptr, &count, available.data()), "vkEnumerateDeviceExtensionProperties"); - auto bytes = AgcDriver::QueryBdaByteFeatures(context.physical, function("vkGetPhysicalDeviceFeatures2"), available); - auto address = AgcDriver::QueryBdaFeatures(context.physical, function("vkGetPhysicalDeviceFeatures2"), available); + VkPhysicalDevice8BitStorageFeatures bytes{}; + VkPhysicalDeviceBufferDeviceAddressFeatures address{}; + try { + bytes = AgcDriver::QueryBdaByteFeatures(context.physical, function("vkGetPhysicalDeviceFeatures2"), available); + address = AgcDriver::QueryBdaFeatures(context.physical, function("vkGetPhysicalDeviceFeatures2"), available); + } catch (const std::exception& error) { + throw TestUnavailable(error.what()); + } const auto queues = function("vkGetPhysicalDeviceQueueFamilyProperties"); queues(context.physical, &count, nullptr); std::vector families(count); queues(context.physical, &count, families.data()); std::uint32_t family = 0; while (family < count && (families[family].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) ++family; - Require(family < count, "no Vulkan compute queue"); + if (family == count) throw TestUnavailable("no Vulkan compute queue"); const float priority = 1; VkDeviceQueueCreateInfo queue{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}; queue.queueFamilyIndex = family; @@ -118,7 +131,8 @@ class Device { int main(int argc, char** argv) { try { RunBdaContractTests(); - if (argc == 2) { + const bool crossRangeOnly = argc == 2 && std::string_view(argv[1]) == "--cross-range-only"; + if (argc == 2 && !crossRangeOnly) { const auto shader = MakeBdaTestShader(0x7fff12340000ULL, 32); std::ofstream file(argv[1], std::ios::binary); file.write(reinterpret_cast(shader.data()), static_cast(shader.size() * sizeof(std::uint32_t))); @@ -130,10 +144,13 @@ int main(int argc, char** argv) { Require(buffer.DeviceAddress() != 0 && buffer.Bytes().size() == 256, "invalid real BDA buffer"); buffer.Bytes()[255] = std::byte{0x5a}; Require(buffer.Bytes()[255] == std::byte{0x5a}, "real BDA buffer mapping failed"); - RunBdaExecutionTests(device.GetContext()); - RunColorTransferTests(device.GetContext()); + RunBdaExecutionTests(device.GetContext(), crossRangeOnly); + if (!crossRangeOnly) RunColorTransferTests(device.GetContext()); std::cout << "Vulkan BDA allocation and execution tests passed\n"; return 0; + } catch (const TestUnavailable& error) { + std::cerr << error.what() << '\n'; + return 77; } catch (const std::exception& error) { std::cerr << error.what() << '\n'; return 1; diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaExecution.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaExecution.cpp index faf2f911c6a..a75dffb1e06 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaExecution.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaExecution.cpp @@ -87,7 +87,7 @@ class Pipeline { } -void RunBdaExecutionTests(const Context& context) { +void RunBdaExecutionTests(const Context& context, bool crossRangeOnly) { namespace Abi = ShaderRecompiler::BdaAbi; Buffer first(context, 3, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); Buffer second(context, 2, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); @@ -124,6 +124,7 @@ void RunBdaExecutionTests(const Context& context) { run(guest, 8, 0x11, static_cast(0)); run(guest + 1, 16, 0x3322, static_cast(0)); run(guest + 1, 32, 0x55443322, static_cast(0)); + if (crossRangeOnly) return; run(guest + 5, 8, 0, Abi::FaultReason::Unmapped, 2, 64); run(guest - 1, 8, 0, Abi::FaultReason::Unmapped); run(std::numeric_limits::max() - 1, 32, 0, Abi::FaultReason::Overflow); diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaShader.hpp b/core/libs/prx/libSceAgcDriver/tests/BdaShader.hpp index 2baa4468a1d..f81dd59133f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaShader.hpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaShader.hpp @@ -7,7 +7,7 @@ std::vector MakeBdaTestShader(std::uint64_t address, std::uint32_t bits, std::int64_t offset = 0); std::vector MakeBdaDwordReadTestShader(std::uint64_t address, std::uint32_t dwords, bool coherent, bool stops); -void RunBdaExecutionTests(const AgcDriver::Graphics::Context& context); +void RunBdaExecutionTests(const AgcDriver::Graphics::Context& context, bool crossRangeOnly = false); void RunBdaContractTests(); #endif