mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Without VK_KHR_fragment_shader_barycentric the recompiler dropped v_interp_p1_f32 and made v_interp_p2_f32 read the attribute Vulkan interpolated, but never wrote the I/J VGPRs: a pixel shader that read them for anything else got 0, and v_interp_mov_f32 of P10/P20 (or P0 of an interpolated input) needed PerVertexKHR and failed pipeline validation. The fallback translation now loads the I/J VGPRs and marks v_interp_p1 and v_interp_p2 with witnesses. After the front-end simplification (SSA, folding, DCE, read-lane and masked-select elimination), HostInterpolationChecker requires every p2 to read its J, and its p1's I, from a barycentric of the parameter's kind, every p1 result to reach only the matching p2 (through a write masked by the p2's EXEC, whose inactive lanes keep the old register), no parameter read as raw vertices and no slot shared by different interpolations. It then lowers the witnesses to the host-interpolated attribute as before, reruns DCE and masked-select elimination, and accepts the program only when no barycentric read remains, so reusing the I/J VGPRs after interpolating keeps host interpolation and the previous SPIR-V. Any other program is translated with the barycentric path and marked as emulated: its barycentrics become vec3 inputs (NoPerspective for the linear weights) and its per-vertex parameters flat vec4[3] inputs, placed in the free locations by LayoutBarycentricEmulation. The driver then inserts a generated geometry stage between the vertex and fragment shaders that copies the position and parameters, writes the one-hot weights of each vertex and the three vertices' parameter values, so the rasterizer interpolates the same weights the extension provides. The stage needs geometryShader and a vertex shader before it; tessellation, mesh and rect-list pipelines, other primitive types and interfaces beyond 32 locations or the device's geometry limits throw. CompiledShaderArtifact carries the emulation (shader disk cache format 21). Hardware snaps window corners to 1/256 pixel before interpolating (measured by yahya308 on an RTX 4070 Laptop and a Radeon 780M in #1547); lavapipe snaps only for coverage (lp_rast.h FIXED_ORDER 8), so the test accepts either reference per pixel at the original 1e-4 margin. Sources: - v_interp_p1_f32/v_interp_p2_f32/v_interp_mov_f32 semantics (P0, P10, P20, I/J): AMD RDNA2 ISA, "Parameter Interpolation". - BaryCoordKHR/BaryCoordNoPerspKHR weights and PerVertexKHR vertex order: SPV_KHR_fragment_shader_barycentric, VK_KHR_fragment_shader_barycentric. - Geometry shader triangle input order and provoking vertex: Vulkan specification, "Primitive Topologies" and "Geometry Shading". - Interpolation decorations decided by the fragment input: Vulkan specification, "Interpolation Decorations". - lavapipe interpolation: Mesa src/gallium/drivers/llvmpipe/lp_rast.h (FIXED_ORDER 8), lp_setup_tri.c (subpixel_snap for coverage only), lp_state_setup.c (init_args, plane setup from float positions).