Repository navigation
feat(agc): rasterize a multisampled draw into one-sample targets at sample 0's locations - #5907
Conversation
|
Rebased onto Tested again on Windows 11 Pro 26200, Release:
|
81a8bd5 to
2ce4e57
Compare
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
With #5907, PPSA07411 (Resident Evil 4) gets past its color-target draws. It now stops on a depth-only draw of the same checkerboard kind, with "the depth target's sample count differs from the rasterizer's". The draw's registers:
I think PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY can stay on this path:
constexpr std::uint32_t SampleDependentInputs = ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::PerspectiveCentroid) | ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::LinearCentroid) | ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::SampleCoverage);
constexpr std::uint32_t PixelCenterPositionInputs = ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::PositionX) | ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::PositionY);bool rasterizesSampleZeroOnly(const Registers& cx, const State& state) {
if (state.samples <= 1 || state.alphaToCoverage || state.perSampleShading || (read(cx, 0x292) & 1u) == 0) return false;
const auto inputs = read(cx, 0x1b3) & read(cx, 0x1b4);
const bool sampleIndexMovesPosition = (inputs & ShaderRecompiler::PixelInputBit(ShaderRecompiler::PixelInput::Ancillary)) != 0 && (inputs & PixelCenterPositionInputs) != 0;
return (inputs & SampleDependentInputs) == 0 && !sampleIndexMovesPosition;
}The early return keeps the I tested it in
Without the change, the new block fails with exactly the game's message. With it, all eight tests backed by Title run with this on top of your PR (Windows Server 2025, RTX 3060, driver 591.86, on a local stack of Debt wording I used in place of "no sample, centroid, ancillary or coverage pixel inputs": "no centroid or coverage pixel inputs ... Such a draw keeps PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY inputs: a pixel shaded once is taken to get sample 0's barycentrics and sample index 0, which is inferred, not measured. ... ANCILLARY with POS_X_FLOAT or POS_Y_FLOAT throws, since reading the sample index makes the host shade per sample, which moves FragCoord from the pixel center to sample 0's location." A side point, which I recorded in the debt entry but did not change: by the same Vulkan rule, the PERSP_CENTER and LINEAR_CENTER inputs this path already accepts (for example None of the other open sample-count PRs cover this draw. #5882, #6014 and #6196 handle MSAA_ENABLE clear, and #5915 handles a one-sample scan into a multisampled depth target; this draw has MSAA_ENABLE set, a 2x raster and a one-sample depth target. AI-assisted: yes |
|
A different one-sample-target case from a GL homebrew. It's data only, in case it matters for this rule. OliSe Player (PPSA01153, catalog 02.001.000) draws through a radeonsi-based GL driver (
This matches radeonsi's polygon and line smoothing. With a one-sample framebuffer, On Not checked: whether AI-assisted: yes |
|
Follow-up to my note above: #6530 now handles the overrasterized draw. It takes only draws whose AI-assisted: yes |
|
Resident Evil Village (PPSA01556) data point for the ANCILLARY + POS_X/Y rule in 7ad8cb8. The setup: #5907 with fdfawef324's rule (as pushed in 7ad8cb8), on What happens: Resident Evil Village gets past the 0x2001 pass. It then stops at its next 2x depth-only pass, whose pixel program reads PERSP_SAMPLE, POS_X/Y_FLOAT and ANCILLARY ( That's the rule refusing ANCILLARY with POS_X/Y. Where the rule comes from: what it guards against, the ancillary's sample field forcing sample shading and moving The combination: with #6470 merged into 7ad8cb8, and the ANCILLARY + POS rule and its two refusal checks dropped:
Either merge order works. A Resident Evil Village boot with the combination follows. |
|
Here is the RE4 (PPSA07411) re-run on 7ad8cb8 I promised. The machine and stack are the same as in my runs above, with 2ce4e57 and my proposed change replaced by your two commits (409f8b6 and 7ad8cb8, cherry-picked unchanged). The stack still has the local diagnostic that adds the decoded sample state to any sample-count refusal message.
Apart from that abort, neither run logged a sample-count refusal or any other driver failure. On RE4, 7ad8cb8 behaves the same as the change I proposed. AI-assisted: yes |
|
@fdfawef324 thanks for the two re-runs. Good to know 7ad8cb8 still gets RE4 to the brightness and play-data screens, and that the cold-cache stop is #5870's. @EagleBearerYS agreed. The ANCILLARY + POS_X/Y refusal is there only because the recompiler gives the ancillary sample field |
|
@simonbronk here is the combined boot. Resident Evil Village (PPSA01556), Windows 11, RTX 3070 Laptop GPU (driver 617.42): It reaches the lit title menu with no driver failure.
The tree (local, not pushed):
One note from after the run: when the window closed, the presenter thread faulted inside NVIDIA's driver ( |
…ample 0's locations A draw whose rasterizer has more samples than its color or depth targets threw "a color target's sample count differs from the rasterizer's" or "the depth target's sample count differs from the rasterizer's". When every target has one sample, MSAA_ENABLE is set, and there is no alpha-to-coverage, no PS_ITER_SAMPLE and no sample-dependent pixel input, only sample 0's coverage reaches the targets, so draw it with one sample at sample 0's location in each pixel of the grid. One-sample depth images are created sample-location compatible when the device allows it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mple-zero path A multisampled rasterizer drawing into one-sample targets keeps PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY inputs, and with PS_ITER_SAMPLE also centroid inputs, since only sample 0's coverage reaches the targets. Coverage inputs, and the sample index with POS_X_FLOAT or POS_Y_FLOAT, still throw. The input rule for the non-iterated case follows fdfawef324's proposal on boykopovar#5907 (PPSA07411). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…get under a 2x scan without MSAA_ENABLE boykopovar#5882 lets a multisampled scan without MSAA_ENABLE through the earlier check, so the draw is now refused where its one-sample color target meets the rasterizer's sample count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7ad8cb8 to
2c1b825
Compare
|
Rebased onto #5882 (merged last night) lets a multisampled scan without MSAA_ENABLE through the earlier
@EagleBearerYS thanks for the Village boot with #6470 and the rule dropped. Reaching the lit title menu with no refusal is what I wanted to see before touching it. I'll drop the ANCILLARY + POS_X/Y rule and its two checks here as soon as #6470 is merged. |
|
Re-checked against current main: the diff is unchanged from the version I reviewed (build and |
|
Re-checked against current main: the diff is unchanged from the version I reviewed (build and |
|
Re-checked against current main: build and |
…povar#5907's tests boykopovar#5907 added a case to multisampleTests that clears MSAA_ENABLE on its 2x rasterizer over a one-sample color target, and expected the color sample-count refusal. With the previous commit, that draw rasterizes the one-sample target as one sample with the standard location, so the case now requires that instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
With #5861 (merged), Onimusha: Way of the Sword (PPSA27836) gets past its checkerboard sample pattern, then stops at the next part of the same technique. It rasterizes with two samples into one-sample targets:
PA_SC_AA_CONFIGSPI_PS_INPUT_ENA/ADDRPA_SC_MODE_CNTL_00x00108001(2 samples)CB_COLOR_ATTRIB0(1 sample)0x302(PERSP_CENTER, POS_X, POS_Y)0x3DB_DEPTH_CONTROL0x002002f1)0x3020x3The sample locations are the checkerboard pattern from #5861: (+4, 0)/16 and (-4, 0)/16, swapped on odd rows.
DecodeStatethrew "a color target's sample count differs from the rasterizer's" and then "the depth target's sample count differs from the rasterizer's". Resident Evil Village (PPSA01556, #5169) uses the same two-sample rasterization into one-sample depth and color targets; its tester approximated it locally.A one-sample target can only keep the coverage of one sample. Vulkan defines this case through
VK_AMD_mixed_attachment_samples: color sample i is covered when raster sample i is covered, and the other raster samples are dropped. That extension exposes how AMD hardware treats a target with fewer samples than the rasterizer. The PS5 GPU is AMD, but this is not measured on PS5 hardware.When nothing else reads the other samples, that is the same as rasterizing one sample at sample 0's location. With the checkerboard grid, that location is (+4, 0)/16 on even rows and (-4, 0)/16 on odd rows. So:
rasterizesSampleZeroOnlyadmits a multisampled rasterizer when every target has one sample,MSAA_ENABLEis set, and there is no alpha-to-coverage and no sample-coverage pixel input:PS_ITER_SAMPLE, centroid inputs still throw. PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY stay: a pixel shaded once is taken to get sample 0's barycentrics and sample index 0 (inferred, not measured). This rule follows fdfawef324's proposal for PPSA07411 below.PS_ITER_SAMPLE(feat(agc): run the pixel program per sample for PS_ITER_SAMPLE #5673), only sample 0's invocation reaches the targets, so sample and centroid inputs are taken at sample 0 and the draw is shaded once (perSampleShadingis cleared). PPSA27836 needs this: during its first scene load it draws withPA_SC_MODE_CNTL_10x06030000andSPI_PS_INPUT_ENA0x2,0xb01(PERSP_SAMPLE, POS_X, POS_Y, POS_W), and without iteration0xf01.0x1b3/0x1b4reads stay behind the early conditions, as one-sample color draws may lack them.rasterizeSampleZerokeeps sample 0's location in each pixel of the grid, sets one sample, and marks the pattern custom or grid as it decodes. A one-sample depth target or the first one-sample color target triggers it. Any other mix still throws the same messages.VK_SAMPLE_COUNT_1_BIT).vkGetPhysicalDeviceMultisamplePropertiesEXTreports a 2x2 grid for one sample on both GPUs here, as for two.ValidateSampleLocationsonly enables sample locations for a one-sample draw when it has custom locations, so other one-sample pipelines are unchanged.SampleLocationsCompatibleDepthnow also answers for one sample. One-sample depth images are created withSAMPLE_LOCATIONS_COMPATIBLE_DEPTHwhere the device allows it, as multisampled ones already were. Vulkan requires that for a depth attachment drawn with custom locations.Tested
main0dab493:ctest -R "agc|shader|video_out"passes 622 of 623 on the RTX 5070 and 619 of 623 on the AMD iGPU. The common failure,agc_driver_store_over_untracked, fails the same way on plainmain(Windows: StoreOverUntracked fails at "the first result was not stored" #6347); the other three on AMD are agc_* tests: 3 of 483 fail on AMD Radeon RX 6400, pass on NVIDIA RTX 4080 SUPER #5271's.main0afa6a6 plus feat(agc): draw line-strip output of NGG geometry programs as mesh lines #5884, fix(agc): rasterize a single-sample scan into a multisampled depth target at the pixel center #5915 and fix(agc): bind a read-only V# over the cached address space through the region that holds it #5815: the three sample-count refusals of the first scene load are gone, and the load goes on to AGC: VK_ERROR_DEVICE_LOST (read invalid) on the first scene load only with host imports (Onimusha: Way of the Sword, PPSA27836, NVIDIA) #6374.mainf343489 with feat(agc): rasterize sample locations that vary between pixels through a 2x2 grid #5861:ctest -j 8on the RTX 5070: 1191 of 1192 pass;check_main_syncfails on a Windows code page and is unrelated;ctest -R "agc|shader|video_out"on the AMD iGPU: 555 of 558 pass; the three failures are the tests of agc_* tests: 3 of 483 fail on AMD Radeon RX 6400, pass on NVIDIA RTX 4080 SUPER #5271, which fail the same way onmainthere.agc_driver_graphics, new cases:ValidateSampleLocationsrefuses them without one-sample sample locations, or without a one-sample grid, and accepts them with both;PS_ITER_SAMPLE, ANCILLARY with POS_X or POS_Y, a two-sample color target beside a one-sample stencil target, andMSAA_ENABLEoff still throw. PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY decode as one sample, also with a one-sample depth target.PS_ITER_SAMPLEalone, with sample and position inputs, and with centroid inputs, decodes as one sample without per-sample shading.AK::EventManager, as Resident Evil Village (PPSA01556) #5169 reports, intermittent). The next run went past both draws. It then stopped at an unrelated texture-dimension mismatch (a 3D T# where the program declares a 2D-array image) that no open PR covers yet.python tools/check_conventions.py --base upstream/main: passes.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file — not applicable.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code