diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 8e6fb4aae..f0b05e071 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -284,6 +284,15 @@ target_link_libraries(agc_structurizer_tests PRIVATE shader_recompiler_agc_drive set_target_properties(agc_structurizer_tests PROPERTIES CXX_EXTENSIONS OFF) configure_windows_unwind(agc_structurizer_tests) +add_test_executable(agc_fragment_barycentric_tests EXCLUDE_FROM_ALL tests/FragmentBarycentric.cpp) +target_include_directories(agc_fragment_barycentric_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/3rdparty/Vulkan-Headers/include) +set_target_properties(agc_fragment_barycentric_tests PROPERTIES CXX_EXTENSIONS OFF) +configure_windows_unwind(agc_fragment_barycentric_tests) +if(BUILD_TESTING) + set_target_properties(agc_fragment_barycentric_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_fragment_barycentric COMMAND agc_fragment_barycentric_tests) +endif() + add_test_executable(agc_subgroup_clock_tests EXCLUDE_FROM_ALL tests/SubgroupClock.cpp Execution/src/SubgroupClock.cpp diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp new file mode 100644 index 000000000..361aadb06 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp @@ -0,0 +1,14 @@ +#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_FRAGMENTBARYCENTRIC_HPP +#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_FRAGMENTBARYCENTRIC_HPP + +#include + +namespace AgcDriver { + +inline bool FragmentShaderBarycentricUsable(VkDriverId driver, bool reported) { + return reported && driver != VK_DRIVER_ID_MOLTENVK; +} + +} + +#endif diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp index 46d037fe7..2d042c39b 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp @@ -5,6 +5,7 @@ #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/PerformanceTimer.hpp" #include "prx/libSceAgcDriver/Execution/include/BdaFeatures.hpp" +#include "prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp" #include "prx/libSceAgcDriver/Execution/include/SubgroupClock.hpp" #include "prx/libSceAgcDriver/Execution/include/PresentationScaler.hpp" #include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp" @@ -756,6 +757,12 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window) : state(std::make_u VkPhysicalDeviceFeatures2 features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &barycentricFeatures}; state->InstanceFunction("vkGetPhysicalDeviceFeatures2")(selected, &features); state->fragmentShaderBarycentric = barycentricFeatures.fragmentShaderBarycentric == VK_TRUE; + if (state->fragmentShaderBarycentric && hasExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + VkPhysicalDeviceDriverProperties driver{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES}; + VkPhysicalDeviceProperties2 driverProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driver}; + state->InstanceFunction("vkGetPhysicalDeviceProperties2")(selected, &driverProperties); + state->fragmentShaderBarycentric = FragmentShaderBarycentricUsable(driver.driverID, state->fragmentShaderBarycentric); + } } VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT interlockFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT}; if (hasExtension(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME)) { diff --git a/core/libs/prx/libSceAgcDriver/tests/FragmentBarycentric.cpp b/core/libs/prx/libSceAgcDriver/tests/FragmentBarycentric.cpp new file mode 100644 index 000000000..6b67d8629 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/FragmentBarycentric.cpp @@ -0,0 +1,33 @@ +#include "prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp" +#include + +namespace { + +struct Case { + VkDriverId driver; + bool reported; + bool usable; +}; + +constexpr Case Cases[]{ + {VK_DRIVER_ID_MOLTENVK, true, false}, + {VK_DRIVER_ID_MOLTENVK, false, false}, + {VK_DRIVER_ID_MESA_RADV, true, true}, + {VK_DRIVER_ID_MESA_RADV, false, false}, + {VK_DRIVER_ID_NVIDIA_PROPRIETARY, true, true}, + {VK_DRIVER_ID_AMD_PROPRIETARY, true, true}, + {VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, false, false}, +}; + +} + +int main() { + int failures = 0; + for (const auto& item : Cases) { + if (AgcDriver::FragmentShaderBarycentricUsable(item.driver, item.reported) != item.usable) { + std::fprintf(stderr, "driver %d reported %d: expected %s fragment barycentric\n", static_cast(item.driver), item.reported ? 1 : 0, item.usable ? "usable" : "unusable"); + ++failures; + } + } + return failures == 0 ? 0 : 1; +}