mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
fix(agc): name the raster order group the pixel interlock needs
The skip named a failure the run never reached: on MoltenVK the test fails while the pipeline is created, because SPIRV-Cross puts a raster order group on the storage buffer the fragment shader updates and MoltenVK passes the descriptor set as an argument buffer, where Metal rejects the attribute. The run never reaches the counter, so it shows no lost update. The test now checks the raster order group first, with the reason the run fails, and the atomics on buffer device addresses second. The global atomics gap moves under the silent stubs, where it belongs: the driver neither refuses the atomic nor reports it to the title.
This commit is contained in:
1 parent
1bf2cdf9f4
commit
d00d8ba52e
7 files changed
+67
-2
No files matched your search
@@ -899,6 +899,15 @@ if(BUILD_TESTING)
|
||||
add_test(NAME agc_bda_atomics COMMAND agc_bda_atomics_tests)
|
||||
endif()
|
||||
|
||||
add_test_executable(agc_raster_order_group_tests EXCLUDE_FROM_ALL tests/RasterOrderGroup.cpp)
|
||||
target_include_directories(agc_raster_order_group_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
|
||||
set_target_properties(agc_raster_order_group_tests PROPERTIES CXX_EXTENSIONS OFF)
|
||||
configure_windows_unwind(agc_raster_order_group_tests)
|
||||
if(BUILD_TESTING)
|
||||
set_target_properties(agc_raster_order_group_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
|
||||
add_test(NAME agc_raster_order_group COMMAND agc_raster_order_group_tests)
|
||||
endif()
|
||||
|
||||
add_test_executable(agc_draw_inputs_in_place_driver_tests EXCLUDE_FROM_ALL tests/DrawInputsInPlace.cpp)
|
||||
target_include_directories(agc_draw_inputs_in_place_driver_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
|
||||
set_target_properties(agc_draw_inputs_in_place_driver_tests PROPERTIES CXX_EXTENSIONS OFF)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_RASTERORDERGROUP_HPP
|
||||
#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_RASTERORDERGROUP_HPP
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
namespace AgcDriver {
|
||||
|
||||
inline bool RasterOrderGroupUsable(VkDriverId driver) {
|
||||
return driver != VK_DRIVER_ID_MOLTENVK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
std::string DriverInfo() const;
|
||||
bool SupportsImageFormat(VkFormat format, VkImageUsageFlags usage) const;
|
||||
bool BdaAtomicsUsable() const;
|
||||
bool RasterOrderGroupUsable() const;
|
||||
bool CalibrateClock(double& gpuNs, std::chrono::steady_clock::time_point& cpu) const;
|
||||
ShaderRecompiler::SpirvTarget Target() const;
|
||||
Graphics::SampleOrder HostSampleOrder(const Graphics::State& graphics) const;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/PerformanceTimer.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/BdaFeatures.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/BdaAtomics.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/RasterOrderGroup.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/DeviceFault.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/FragmentBarycentric.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Float32FlushControl.hpp"
|
||||
@@ -3868,6 +3869,10 @@ bool VulkanDevice::BdaAtomicsUsable() const {
|
||||
return AgcDriver::BdaAtomicsUsable(state->driverId);
|
||||
}
|
||||
|
||||
bool VulkanDevice::RasterOrderGroupUsable() const {
|
||||
return AgcDriver::RasterOrderGroupUsable(state->driverId);
|
||||
}
|
||||
|
||||
bool VulkanDevice::CalibrateClock(double& gpuNs, std::chrono::steady_clock::time_point& cpu) const {
|
||||
if (state->calibratedTimestamps == nullptr) return false;
|
||||
const std::array<VkCalibratedTimestampInfoKHR, 2> domains{VkCalibratedTimestampInfoKHR{VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR, nullptr, VK_TIME_DOMAIN_DEVICE_KHR}, VkCalibratedTimestampInfoKHR{VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR, nullptr, state->hostTimeDomain}};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/RasterOrderGroup.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
namespace {
|
||||
|
||||
struct Case {
|
||||
VkDriverId driver;
|
||||
bool usable;
|
||||
};
|
||||
|
||||
constexpr Case Cases[]{
|
||||
{VK_DRIVER_ID_AMD_PROPRIETARY, true},
|
||||
{VK_DRIVER_ID_AMD_OPEN_SOURCE, true},
|
||||
{VK_DRIVER_ID_MESA_RADV, true},
|
||||
{VK_DRIVER_ID_NVIDIA_PROPRIETARY, true},
|
||||
{VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, true},
|
||||
{VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, true},
|
||||
{VK_DRIVER_ID_MESA_LLVMPIPE, true},
|
||||
{VK_DRIVER_ID_MOLTENVK, false},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
int failures = 0;
|
||||
for (const auto& item : Cases) {
|
||||
if (AgcDriver::RasterOrderGroupUsable(item.driver) != item.usable) {
|
||||
std::fprintf(stderr, "driver %d: expected a raster order group to be %s\n", static_cast<int>(item.driver), item.usable ? "usable" : "unusable");
|
||||
++failures;
|
||||
}
|
||||
}
|
||||
return failures == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -219,6 +219,10 @@ int main() {
|
||||
std::puts("skipped, the device lacks fragmentShaderPixelInterlock");
|
||||
return VulkanTestSkipped;
|
||||
}
|
||||
if (!device->RasterOrderGroupUsable()) {
|
||||
std::puts("skipped, the device does not support the raster order group the pixel interlock needs");
|
||||
return VulkanTestSkipped;
|
||||
}
|
||||
if (!device->BdaAtomicsUsable()) {
|
||||
std::puts("skipped, the device does not support atomics on buffer device addresses");
|
||||
return VulkanTestSkipped;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
- [sceAgcDriverRegisterDefaultOwner](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - takes one uint32 owner by value (OpenAGC `include/agcdriver.h`, SharpEmu `AgcExports.DriverResources.cs`) and returns 0 without recording it. PPSA21480 treats the code 0x8A6C9018 it returned before as fatal. Console behaviour is unverified: OpenAGC describes the function as a firmware 5.50 stub that returns 0x8A6C9018, SharpEmu returns 0
|
||||
- [sceAgcDriverSetResourceRegistrationInfo](../../../core/libs/prx/libSceAgcDriver/Resource/src/Registration.cpp) (libSceAgcDriver) - returns 0 without storing the info, as the retail `libSceAgcDriver.sprx` body does; registration is unavailable, so nothing reads it back.
|
||||
|
||||
- [Global atomics on buffer device addresses](../../../core/libs/prx/libSceAgcDriver/Execution/include/BdaAtomics.hpp) (libSceAgcDriver) - a flat atomic reaches its target through a Vulkan buffer device address (`OpConvertUToPtr` over a `PhysicalStorageBuffer` pointer), so the read-modify-write is atomic only where the driver guarantees atomics on such an address. MoltenVK does not: Metal has no atomic on a device pointer, so the update is a load and a store and concurrent updates to one address are silently lost. The driver does not refuse the shader; `BdaAtomicsUsable` reports the limitation and only `agc_driver_pixel_interlock` consults it. `agc_driver_global_atomics` cannot cover the case: every lane has its own address, so it checks an uncontended read-modify-write. A title that counts or locks through a flat atomic on macOS counts wrong, and no title has been measured.
|
||||
|
||||
### Unknown function info
|
||||
@@ -276,7 +275,7 @@
|
||||
- [Long Windows pipeline-cache paths](../../../core/libs/prx/libSceAgcDriver/Graphics/src/PipelineCache.cpp): `readHeader` and the failed-read existence check still use ordinary paths. A filename beyond MAX_PATH can prevent header reuse or be reported missing; the shared content reader and journal normalization do not cover these calls.
|
||||
- [DB_RENDER_CONTROL.STENCIL_CLEAR_ENABLE without a stencil plane](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver): a stencil clear on a depth target whose `DB_STENCIL_INFO` format is `STENCIL_INVALID` is dropped; the depth clear and color writes proceed. AMD PAL ([`gfx9RsrcProcMgr.cpp`](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32/src/core/hw/gfxip/rpm/gfx9/gfx9RsrcProcMgr.cpp)) and radeonsi (`si_clear.c`) never set the bit without a stencil plane, and shadPS4 drops it the same way (`vk_rasterizer.cpp`, `StencilValid`). No source states what the hardware does with the bit then; the console was not measured. A read-only stencil plane still throws
|
||||
- [Swept write-only staging](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp) (libSceAgcDriver): on a discrete GPU a write-only element whose V# stride is wider than the widest buffer store (16 bytes) and that a direct dispatch sweeps is staged in a device-local shadow. The shadow still takes a copy-in, because the copy-back covers the whole element and the stores may leave part of each record unwritten. A sweep proven to write every byte of the element (from the offsets and widths of its stores within the record) could skip the copy-in, about 10 ms per frame in Diablo II: Resurrected; that proof is not made. Store widths are not recorded per instruction either, so a record of 16 bytes or less stays in place even when its stores are narrower.
|
||||
- [Pixel interlock on a device without atomic buffer device addresses](../../../core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp) (libSceAgcDriver) - `agc_driver_pixel_interlock` skips where `BdaAtomicsUsable` is false, because it is the only test that counts overlapping updates to one address and that count cannot be right without the guarantee. On MoltenVK the test also fails before it reaches the count, at `vkCreateGraphicsPipelines` with `Vulkan result -3`: MoltenVK's own SPIRV-Cross refuses `raster_order_group` in an argument buffer (`type 'const constant spvDescriptorSetBuffer0 &' is not valid for attribute 'buffer'`). The skip covers that failure too, so on macOS neither it nor the lost updates are visible. Neither is fixed here: resolving the atomic to a descriptor-bound buffer instead of a device address would change the BDA table ABI, whose ranges carry a flat device address.
|
||||
- [Pixel interlock on a device without atomic buffer device addresses](../../../core/libs/prx/libSceAgcDriver/tests/execution/PixelInterlock.cpp) (libSceAgcDriver) - `agc_driver_pixel_interlock` skips where `BdaAtomicsUsable` is false, because it is the only test that counts overlapping updates to one address and that count cannot be right without the guarantee. On MoltenVK it also fails before it reaches the count, at `vkCreateGraphicsPipelines` with `Vulkan result -3`: MoltenVK's own SPIRV-Cross refuses `raster_order_group` in an argument buffer, so `RasterOrderGroupUsable` covers that failure first and the skip names it. With the argument buffers off (`MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0`) the pipeline compiles and the plain draws pass, and only then does the missing atomic show as lost updates. Neither is fixed here: a descriptor-bound atomic would change the BDA table ABI, whose ranges carry a flat device address
|
||||
|
||||
### Opt-in draw paths
|
||||
|
||||
|
||||
Reference in new issue
Block a user