From ff9962b88a068b6af432f6e0e5d08247f6b491e6 Mon Sep 17 00:00:00 2001 From: "john.maia" Date: Wed, 7 Oct 2026 17:39:24 +0100 Subject: [PATCH] test(agc): run agc_driver_bda_device_tests under ctest The BDA device test was built only on request and never registered, so it ran nowhere. Register it with the other AGC driver tests. Pick the Vulkan device the way VulkanDevice does, a discrete GPU over an integrated one, instead of the first enumerated device, so the test runs on the same GPU as the runtime on hosts with an iGPU. Without a usable device it exits 77, as OpenVulkanTestDevice does, unless ANYPS5_REQUIRE_VULKAN is set. On a CPU device the BDA execution tests are not run: llvmpipe loads through the null pointer of a branch that is not taken and the process segfaults (Mesa #16515, #16217). The contract, allocation and color transfer tests still run there. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libSceAgcDriver/CMakeLists.txt | 2 +- .../prx/libSceAgcDriver/tests/BdaDevice.cpp | 45 ++++++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index a850b0a93085..b9fa8c92adf7 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -521,7 +521,7 @@ foreach(agcExecutionTestSource IN LISTS agcExecutionTestSources) endforeach() if(BUILD_TESTING) - foreach(agcTest IN ITEMS agc_driver_tests agc_shader_memory_tests agc_structurizer_tests agc_spirv_module_tests agc_dpp_write_tests agc_masked_select_tests agc_vop1_control_decode_tests agc_validate_program_tests agc_shader_disk_cache_tests agc_shader_control_flow_tests agc_driver_flip_tests agc_driver_pm4_tests agc_driver_graphics_tests ${agcExecutionTests}) + foreach(agcTest IN ITEMS agc_driver_tests agc_shader_memory_tests agc_structurizer_tests agc_spirv_module_tests agc_dpp_write_tests agc_masked_select_tests agc_vop1_control_decode_tests agc_validate_program_tests agc_shader_disk_cache_tests agc_shader_control_flow_tests agc_driver_flip_tests agc_driver_pm4_tests agc_driver_graphics_tests agc_driver_bda_device_tests ${agcExecutionTests}) string(REGEX REPLACE "_tests$" "" agcTestName "${agcTest}") set_target_properties(${agcTest} PROPERTIES EXCLUDE_FROM_ALL OFF) add_test(NAME ${agcTestName} COMMAND ${agcTest}) diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp index 484d60a7a474..8d73dada82be 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaDevice.cpp @@ -6,7 +6,9 @@ #include "prx/libSceAgcDriver/Graphics/include/Resources.hpp" #include #include +#include #include +#include #include namespace AgcDriver::Graphics { @@ -42,7 +44,27 @@ class Device { Require(count != 0, "no Vulkan device"); std::vector devices(count); Check(enumerate(instance, &count, devices.data()), "vkEnumeratePhysicalDevices"); - context.physical = devices.front(); + const auto rankDeviceType = [](VkPhysicalDeviceType type) { + switch (type) { + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 3; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 2; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 1; + default: return 0; + } + }; + const auto physicalProperties = function("vkGetPhysicalDeviceProperties"); + int selectedRank = -1; + for (const auto physical : devices) { + VkPhysicalDeviceProperties candidate{}; + physicalProperties(physical, &candidate); + if (candidate.apiVersion < VK_API_VERSION_1_1) continue; + const int rank = rankDeviceType(candidate.deviceType); + if (rank <= selectedRank) continue; + context.physical = physical; + selectedRank = rank; + cpu = candidate.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU; + } + Require(context.physical != VK_NULL_HANDLE, "no Vulkan 1.1 device"); const auto extensions = function("vkEnumerateDeviceExtensionProperties"); Check(extensions(context.physical, nullptr, &count, nullptr), "vkEnumerateDeviceExtensionProperties"); std::vector available(count); @@ -90,6 +112,7 @@ class Device { ~Device() { release(); } const Context& GetContext() const { return context; } + bool RunsOnCpu() const { return cpu; } private: template @@ -111,6 +134,7 @@ class Device { PFN_vkGetInstanceProcAddr instanceProc = nullptr; VkInstance instance = VK_NULL_HANDLE; Context context{}; + bool cpu = false; }; } @@ -125,13 +149,24 @@ int main(int argc, char** argv) { Require(static_cast(file), "cannot save BDA test SPIR-V"); return 0; } - Device device; - Buffer buffer(device.GetContext(), 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + std::unique_ptr device; + try { + device = std::make_unique(); + } catch (const std::exception& error) { + if (std::getenv("ANYPS5_REQUIRE_VULKAN") != nullptr) throw; + std::cout << "skipped, no usable Vulkan device: " << error.what() << '\n'; + return 77; + } + Buffer buffer(device->GetContext(), 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); 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()); + if (device->RunsOnCpu()) { + std::cout << "CPU Vulkan device: BDA execution not tested\n"; + } else { + RunBdaExecutionTests(device->GetContext()); + } + RunColorTransferTests(device->GetContext()); std::cout << "Vulkan BDA allocation and execution tests passed\n"; return 0; } catch (const std::exception& error) {