You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AGC: root cause of the AMD proprietary failures behind the robustBufferAccess2 exclusion (#7351) is still open #7376
#7351 keeps robustBufferAccess2 off on VK_DRIVER_ID_AMD_PROPRIETARY so three execution tests pass again on AMD's Windows driver. It works around the failures and does not explain them. This issue is to find the root cause, so the exclusion doesn't stay forever.
What #7351 changed.robustBufferAccess2 is now enabled on every device that has it except AMD's proprietary driver. On that driver, guest memory loads keep the selected-load form that devices without the feature use. The device feature enable, the SPIR-V target flag (and so the shader cache key) and the load guards all follow the same predicate. Other drivers are unchanged.
What the author measured (RX 6700 XT, Windows, driver 32.0.21045.5002, from #7351). #4048 was bisected as the cause. A three-way split on main5229b5b82:
main with
layered_volume_draw
layered_volume_vertex
subvector_loop
nothing changed
fails
fails
fails
robustBufferAccess2 not enabled (so no selected loads)
passes
passes
passes
feature enabled, target.robustBufferAccess2 = false (loads keep their selections)
fails
fails
passes
The two layered-volume tests fail as soon as the device feature is enabled on this driver, whatever the recompiler emits. The volume keeps its sentinel, so nothing reached it.
agc_driver_subvector_loop fails only with the selected loads: the high half of the wave64 never runs the loop body (lane 0 exec hi after the loop is 0, expected 4294967295). A wave64 compute probe that loads Input[lane] and stores it back is correct in every lane, and so is a probe of the vertex shader's two loads, so the load itself is not simply wrong.
Open questions
Is the layered-volume failure an AMD driver bug with the feature enabled, or something AnyPS5 does with layered or volume images that only breaks under robustness2?
Cost of the exclusion. On AMD Windows, shader block counts go back to what they were before #4048. For one test title the debt doc records 16,983 blocks against 5,907 with #4048's branch-free loads, so compile time returns to what it was a day earlier. It is not a regression against main from before #4048.
How to check a fix. On an AMD proprietary driver, run agc_driver_layered_volume_draw, agc_driver_layered_volume_vertex and agc_driver_subvector_loop with the exclusion removed. There is no AMD device in CI, so this needs a contributor with an AMD Windows machine. The predicate has a unit test (agc_robust_buffer_access), which only covers the driver-ID check.
@Mouad-Scriptz-0, you wrote #4048; could you look at whether the selected loads can produce the subvector_loop result? @thuanquang has the AMD setup from #7351.
Data point from RDNA 3.5: with robustBufferAccess2 turned back on, all three tests pass on AMD's proprietary driver here. So the failures do not seem to follow the driver ID alone.
Radeon 860M (RDNA 3.5, 1002:1114, APU), AMD driver 32.0.13058.8001 (Vulkan driver info 24.30.58.08, LLPC), Windows 11 Home 26300, WinLibs GCC 15.2.0, Release. Build: main1c523bdb4 + #6308 + #7264 (neither touches these paths).
RobustBufferAccess2Usable
layered_volume_draw
layered_volume_vertex
subvector_loop
as on main (off on VK_DRIVER_ID_AMD_PROPRIETARY)
3/3 pass
3/3 pass
3/3 pass
forced to true
3/3 pass
3/3 pass
3/3 pass
With the predicate forced to true, agc_driver_lds_lock_budget prints robustBufferAccess2=1, so the feature and the recompiler target both followed it. The failures measured in #7351 came from RDNA 2 on drivers 32.0.21045.5002 (RX 6700 XT) and 32.0.21036.18 (iGPU, #7344). That points at an architecture or driver branch rather than at every AMD proprietary device.
The recompiler does not emit the subvector loop differently when loads are selected; the two forms of this test program differ only around the one guest load, before the exec ballot.
What I compared.agc_driver_subvector_loop's ExecKeptCode, recompiled with the test's own request at a 64-lane host subgroup (the RDNA 2 path, not the 32-lane split this Intel machine takes), once with target.robustBufferAccess2 = true and once with false, both on 33f191da8. Both modules pass spirv-val --target-env vulkan1.3. After ID renumbering, the whole diff is:
The v_cmpx ballot, the s_subvector_loop_begin/_end bookkeeping, the loop construct and the nine stores are identical. So on this driver the compiler generates different code for the loop from the same SPIR-V once the load upstream is a select over a robust index rather than a branch.
What the printed columns say. The failing case is "initial exec high half": lanes 0 to 31 inactive after the compare. For lane 0 the columns before the failing one matched, including s38 after the loop = 0. The begin instruction only writes s38 when exec is nonzero, and with exec_lo = 0 it writes exec_lo, so the begin saw exec_hi ≠ 0: the ballot at v_cmpx was right. Yet lanes 32 to 63 never ran the body and exec_hi after the loop is 0. Both fit the end instruction reading exec_hi as 0: highSet false, counterZero true, so the loop exits with exec_lo = s38 = 0 and exec_hi unchanged at 0. The value tracked for exec_hi is lost between begin and end, with exec_lo equal to zero, in the driver's codegen.
Three things that would locate it, all needing an AMD Windows machine:
@thuanquang, capture the pipeline with APS5_DUMP_COMPUTE_PIPELINES=<dir> in both forms and compile the two SPIR-V modules with Radeon GPU Analyzer for gfx1031. The ISA around the loop is the only place the difference can show.
A probe that keeps the selected load but feeds v_cmpx from an ALU-derived lane mask (v_mbcnt ≥ 32) instead of the loaded value. If it passes, the trigger is the load-to-exec dataflow; if it still fails, the code shape alone.
I can attach the four disassemblies (both forms at 32 and 64 lanes) if useful.
A data point that splits the three failures in two. Setup: RX 6700 XT, AMD driver 32.0.21045.5002, Windows 11, main3e3e8b905 with RobustBufferAccess2Usable forced to true.
Run under their usual names, all three fail, as in #7351. AMD's Windows driver keeps an on-disk pipeline cache per executable, so I also ran renamed copies of the test executables, which start with an empty cache:
subvector_loop fails even with an empty cache:lane 0 exec hi after the loop is 0, expected 4294967295, as before. So that part is real on this driver, and @Mouad-Scriptz-0's points 1 and 3 still apply to it.
For point 2, I can't switch this machine's driver. For point 1, I don't have Radeon GPU Analyzer installed. I can dump both pipelines with APS5_DUMP_COMPUTE_PIPELINES if someone with RGA wants the SPIR-V.
If this holds up, #7351's exclusion could narrow to what subvector_loop needs, rather than every AMD proprietary device.
@thuanquang good point. My earlier runs reused the same executables with the feature off and then on, so they could have hit cached pipelines. I reran here with renamed copies, so the driver cache starts empty, and with RobustBufferAccess2Usable forced to true on main6efb7261b. Radeon 860M (RDNA 3.5), driver 32.0.13058.8001, Windows 11 26300, same ANYPS5_NO_SHADER_CACHE=1 APS5_NO_PIPELINE_JOURNAL=1 as ctest:
So subvector_loop passes from an empty cache here too, while it fails on your RX 6700 XT on 32.0.21045.5002. On this machine that is not a cache artefact. It fits @Mouad-Scriptz-0's reading of a codegen difference for the selected-load form. Whether that difference comes from the RDNA 2 target or from the 32.0.21045 compiler, these two machines can't separate: both the architecture and the driver differ.
The four disassemblies would help narrow this down. Could you attach the 32-lane and 64-lane modules for both target.robustBufferAccess2 settings, with the exact source commit and AMD driver/device recorded for each? The existing comparison suggests the relevant difference is around the exec loop after the selected load, so preserving the surrounding instructions and the SPIR-V-to-ISA mapping would make the comparison actionable. I will review them if you post them.
@MarcZX10@Mouad-Scriptz-0 I read the ISA back from AMD's driver with VK_KHR_pipeline_executable_properties: RX 6700 XT, driver 32.0.21045.5002, main3e3e8b905, ExecKeptCode. The pipeline runs at 64 lanes on this device, so there is no 32-lane module to compare here. In the robustBufferAccess2 form, the driver computes exec_lo == 0 in s_subvector_loop_begin from the SCC of the guard's 64-bit s_and_b64. So it tests the whole mask, and with exec_lo 0 and exec_hi set, exec_hi is selected to 0. That is the lost high half. The SPIR-V is right and the driver miscompiles it. Testing the empty mask as (exec_lo | exec_hi) == 0 avoids it: #7623, with the three ISA excerpts.
With that, subvector_loop passes here with robustBufferAccess2 on. The layered-volume failures are the cache-order effect from my earlier comment, so I left the exclusion in place.
Point 3 (probe), for the record: feeding the v_cmpx from v_mbcnt, with the selected load kept but unused, passes 2 of 2. The unchanged program fails 2 of 2. That fits the reading above, though I did not read that probe's ISA.
Thanks for the ISA trace. This isolates the subvector_loop failure to RADV’s lowering of the empty-mask check: it reads the combined 64-bit mask through SCC, so an empty low half can incorrectly discard the nonempty high half. Open PR #7623 tests the empty exec mask with one compare and includes the AMD ISA evidence; that part now has a concrete proposed fix. The layered-volume failures remain a separate cache-order question, so keeping the AMD-driver feature exclusion until that path is explained still seems warranted.
The layered-volume part, measured: it is the GPL cache-order effect from #4768, and #6436 removes it. robustBufferAccess2 doesn't cause it. (@MarcZX10, a note on the driver: this is AMD's Windows driver, amdvlk64.dll 32.0.21045.5002, not RADV.)
Setup: RX 6700 XT (gfx1031), Windows 11 26200, main023106ae4 plus a local environment switch that turns robustBufferAccess2 on for AMD (off when unset). Each row is one renamed copy of agc_driver_layered_volume_draw_tests, so the driver cache starts empty, run step by step in the modes of the three ctest cases (draw, --vertex-only, --vertex-only with APS5_NO_GPL=1), with ANYPS5_NO_SHADER_CACHE=1 and APS5_NO_PIPELINE_JOURNAL=1. Every row ran twice, with the same result both times.
GPL off; GPL on (draw, vertex); GPL off. robust2 on
both GPL-on steps fail
all pass
the same, robust2 off
both GPL-on steps fail
all pass
GPL on (draw, vertex); GPL off; GPL on. robust2 on
the GPL-off step fails
all pass
the same, robust2 off
the GPL-off step fails
all pass
robust2 off, on, off; GPL on
all pass
all pass
robust2 off, on, off; GPL off
all pass
all pass
Every failure prints vertex draw: slice 1 texel (0, 0) channel 0 is 64, expected 255 (the band of layer 0). A run that compiles takes about 0.42 s, a run served from the cache about 0.26 s. The first run after robust2 changes takes the compile time, so robust2 gets cache entries of its own, and changing it never failed a run. Which mode fails depends only on which GPL mode compiled the pipelines first. That also fits the #7351 bisect: turning robust2 on gave these pipelines new cache entries, and the GPL mode that compiled them first decided which tests failed from then on.
With #6436 and #7623 both applied, on the same base with robust2 forced on, agc_driver_subvector_loop passes and every sequence in the table passes, twice. A full ctest --parallel 4 --timeout 120 with robust2 forced on (1508 tests) fails these AGC tests: agc_driver_lds_mixed_width_atomics and agc_driver_lds_lock_budget, which fail on main here without the switch too (#6976). agc_driver_layered_volume_vertex_no_gpl, which fails on main here (#4768), passes. log_macros and log_macros_timestamps fail in every local build here, because ccache rewrites __FILE__. The other six failures were CPU-bound tests that timed out or aborted while parallel builds held the CPU at 100%: guest_* and audio_out2_timing, which link libkernel, libc or libSceAudioOut but not the AGC driver. Rerun one at a time with the switch on, five of them pass; guest_pthread_start (10,000 thread starts, libkernel and libc only) timed out again under the same load.
So once #6436 and #7623 are in, nothing behind #7351's AMD exclusion fails on this GPU and driver, and the exclusion could be dropped. As for caches users already have: in these runs, a run with robust2 on that started from a cache filled with it off compiled anew (0.42 s) and never failed. I can open the PR that drops the exclusion, with Depends on both, once they merge.
Thanks for the measurements, and for correcting the driver identification. This separates the reports into two paths: #7623 addresses the AMD proprietary driver miscompile in subvector_loop, while #6436 addresses the GPL cache-order effect seen by the layered-volume tests. Since both PRs are still open, #7351’s AMD robustBufferAccess2 exclusion should remain until the combined changes are on main and the four reported execution tests plus the layered-volume cases are rerun on the affected AMD driver. The issue now has a concrete explanation for both failure groups; the remaining check is their combined post-merge behavior.
@MarcZX10#7623 and #7828 are both on main now, so I reran the cases from this issue on the RX 6700 XT (AMD's Windows driver 32.0.21045.5002) with the exclusion removed: #8267.
With robustBufferAccess2 on (agc_driver_lds_lock_budget reports robustBufferAccess2=1):
agc_driver_layered_volume_draw, agc_driver_layered_volume_vertex, agc_driver_layered_volume_vertex_no_gpl and agc_driver_subvector_loop pass 3 of 3.
The layered-volume sequences from my earlier comment (renamed executables, empty driver cache, both library-mode orders, twice each) pass at every step.
agc_driver_subvector_loop_tests passes with libraries on then off, and off then on.
#6436 is still open. With #7828 on main the device is the same in both library modes, which removes the cross-mode cache effect behind the layered-volume failures, and the sequences pass without #6436. The full suite fails the same 4 tests with and without the change, and the Khronos validation layer reports no VUID- message on either side. Details are in #8267.
Activity
LeandroLP23 commentedon Oct 18, 2026
Data point from RDNA 3.5: with
robustBufferAccess2turned back on, all three tests pass on AMD's proprietary driver here. So the failures do not seem to follow the driver ID alone.Radeon 860M (RDNA 3.5,
1002:1114, APU), AMD driver 32.0.13058.8001 (Vulkan driver info 24.30.58.08, LLPC), Windows 11 Home 26300, WinLibs GCC 15.2.0, Release. Build:main1c523bdb4+ #6308 + #7264 (neither touches these paths).RobustBufferAccess2Usablemain(off onVK_DRIVER_ID_AMD_PROPRIETARY)trueWith the predicate forced to
true,agc_driver_lds_lock_budgetprintsrobustBufferAccess2=1, so the feature and the recompiler target both followed it. The failures measured in #7351 came from RDNA 2 on drivers 32.0.21045.5002 (RX 6700 XT) and 32.0.21036.18 (iGPU, #7344). That points at an architecture or driver branch rather than at every AMD proprietary device.AI-assisted
Mouad-Scriptz-0 commentedon Oct 18, 2026
The recompiler does not emit the subvector loop differently when loads are selected; the two forms of this test program differ only around the one guest load, before the exec ballot.
What I compared.
agc_driver_subvector_loop'sExecKeptCode, recompiled with the test's own request at a 64-lane host subgroup (the RDNA 2 path, not the 32-lane split this Intel machine takes), once withtarget.robustBufferAccess2 = trueand once withfalse, both on33f191da8. Both modules passspirv-val --target-env vulkan1.3. After ID renumbering, the whole diff is:The
v_cmpxballot, thes_subvector_loop_begin/_endbookkeeping, the loop construct and the nine stores are identical. So on this driver the compiler generates different code for the loop from the same SPIR-V once the load upstream is a select over a robust index rather than a branch.What the printed columns say. The failing case is "initial exec high half": lanes 0 to 31 inactive after the compare. For lane 0 the columns before the failing one matched, including
s38 after the loop= 0. The begin instruction only writess38when exec is nonzero, and withexec_lo= 0 it writesexec_lo, so the begin sawexec_hi≠ 0: the ballot atv_cmpxwas right. Yet lanes 32 to 63 never ran the body andexec_hi after the loopis 0. Both fit the end instruction readingexec_hias 0:highSetfalse,counterZerotrue, so the loop exits withexec_lo=s38= 0 andexec_hiunchanged at 0. The value tracked forexec_hiis lost between begin and end, withexec_loequal to zero, in the driver's codegen.Three things that would locate it, all needing an AMD Windows machine:
APS5_DUMP_COMPUTE_PIPELINES=<dir>in both forms and compile the two SPIR-V modules with Radeon GPU Analyzer for gfx1031. The ISA around the loop is the only place the difference can show.v_cmpxfrom an ALU-derived lane mask (v_mbcnt≥ 32) instead of the loaded value. If it passes, the trigger is the load-to-exec dataflow; if it still fails, the code shape alone.I can attach the four disassemblies (both forms at 32 and 64 lanes) if useful.
thuanquang commentedon Oct 18, 2026
A data point that splits the three failures in two. Setup: RX 6700 XT, AMD driver 32.0.21045.5002, Windows 11,
main3e3e8b905withRobustBufferAccess2Usableforced totrue.Run under their usual names, all three fail, as in #7351. AMD's Windows driver keeps an on-disk pipeline cache per executable, so I also ran renamed copies of the test executables, which start with an empty cache:
agc_driver_layered_volume_drawagc_driver_subvector_looprobustBufferAccess2was off and doesn't key them on the feature. With an empty cache, the same build passes. That would answer open question 1, and it may be why @LeandroLP23's RDNA 3.5 machine passes everything.subvector_loopfails even with an empty cache:lane 0 exec hi after the loop is 0, expected 4294967295, as before. So that part is real on this driver, and @Mouad-Scriptz-0's points 1 and 3 still apply to it.For point 2, I can't switch this machine's driver. For point 1, I don't have Radeon GPU Analyzer installed. I can dump both pipelines with
APS5_DUMP_COMPUTE_PIPELINESif someone with RGA wants the SPIR-V.If this holds up, #7351's exclusion could narrow to what
subvector_loopneeds, rather than every AMD proprietary device.LeandroLP23 commentedon Oct 18, 2026
@thuanquang good point. My earlier runs reused the same executables with the feature off and then on, so they could have hit cached pipelines. I reran here with renamed copies, so the driver cache starts empty, and with
RobustBufferAccess2Usableforced totrueonmain6efb7261b. Radeon 860M (RDNA 3.5), driver 32.0.13058.8001, Windows 11 26300, sameANYPS5_NO_SHADER_CACHE=1 APS5_NO_PIPELINE_JOURNAL=1as ctest:agc_driver_layered_volume_drawagc_driver_layered_volume_draw --vertex-onlyagc_driver_subvector_loopagc_driver_lds_mixed_width_atomics --lock-budget(robustBufferAccess2=1)So
subvector_looppasses from an empty cache here too, while it fails on your RX 6700 XT on 32.0.21045.5002. On this machine that is not a cache artefact. It fits @Mouad-Scriptz-0's reading of a codegen difference for the selected-load form. Whether that difference comes from the RDNA 2 target or from the 32.0.21045 compiler, these two machines can't separate: both the architecture and the driver differ.AI-assisted
MarcZX10 commentedon Oct 18, 2026
The four disassemblies would help narrow this down. Could you attach the 32-lane and 64-lane modules for both
target.robustBufferAccess2settings, with the exact source commit and AMD driver/device recorded for each? The existing comparison suggests the relevant difference is around the exec loop after the selected load, so preserving the surrounding instructions and the SPIR-V-to-ISA mapping would make the comparison actionable. I will review them if you post them.thuanquang commentedon Oct 18, 2026
@MarcZX10 @Mouad-Scriptz-0 I read the ISA back from AMD's driver with
VK_KHR_pipeline_executable_properties: RX 6700 XT, driver 32.0.21045.5002,main3e3e8b905,ExecKeptCode. The pipeline runs at 64 lanes on this device, so there is no 32-lane module to compare here. In therobustBufferAccess2form, the driver computesexec_lo == 0ins_subvector_loop_beginfrom the SCC of the guard's 64-bits_and_b64. So it tests the whole mask, and withexec_lo0 andexec_hiset,exec_hiis selected to 0. That is the lost high half. The SPIR-V is right and the driver miscompiles it. Testing the empty mask as(exec_lo | exec_hi) == 0avoids it: #7623, with the three ISA excerpts.With that,
subvector_looppasses here withrobustBufferAccess2on. The layered-volume failures are the cache-order effect from my earlier comment, so I left the exclusion in place.Point 3 (probe), for the record: feeding the
v_cmpxfromv_mbcnt, with the selected load kept but unused, passes 2 of 2. The unchanged program fails 2 of 2. That fits the reading above, though I did not read that probe's ISA.MarcZX10 commentedon Oct 18, 2026
Thanks for the ISA trace. This isolates the
subvector_loopfailure to RADV’s lowering of the empty-mask check: it reads the combined 64-bit mask through SCC, so an empty low half can incorrectly discard the nonempty high half. Open PR #7623 tests the empty exec mask with one compare and includes the AMD ISA evidence; that part now has a concrete proposed fix. The layered-volume failures remain a separate cache-order question, so keeping the AMD-driver feature exclusion until that path is explained still seems warranted.thuanquang commentedon Oct 18, 2026
The layered-volume part, measured: it is the GPL cache-order effect from #4768, and #6436 removes it.
robustBufferAccess2doesn't cause it. (@MarcZX10, a note on the driver: this is AMD's Windows driver,amdvlk64.dll32.0.21045.5002, not RADV.)Setup: RX 6700 XT (gfx1031), Windows 11 26200,
main023106ae4plus a local environment switch that turnsrobustBufferAccess2on for AMD (off when unset). Each row is one renamed copy ofagc_driver_layered_volume_draw_tests, so the driver cache starts empty, run step by step in the modes of the three ctest cases (draw,--vertex-only,--vertex-onlywithAPS5_NO_GPL=1), withANYPS5_NO_SHADER_CACHE=1andAPS5_NO_PIPELINE_JOURNAL=1. Every row ran twice, with the same result both times.mainmain+ #6436Every failure prints
vertex draw: slice 1 texel (0, 0) channel 0 is 64, expected 255 (the band of layer 0). A run that compiles takes about 0.42 s, a run served from the cache about 0.26 s. The first run after robust2 changes takes the compile time, so robust2 gets cache entries of its own, and changing it never failed a run. Which mode fails depends only on which GPL mode compiled the pipelines first. That also fits the #7351 bisect: turning robust2 on gave these pipelines new cache entries, and the GPL mode that compiled them first decided which tests failed from then on.With #6436 and #7623 both applied, on the same base with robust2 forced on,
agc_driver_subvector_looppasses and every sequence in the table passes, twice. A fullctest --parallel 4 --timeout 120with robust2 forced on (1508 tests) fails these AGC tests:agc_driver_lds_mixed_width_atomicsandagc_driver_lds_lock_budget, which fail onmainhere without the switch too (#6976).agc_driver_layered_volume_vertex_no_gpl, which fails onmainhere (#4768), passes.log_macrosandlog_macros_timestampsfail in every local build here, because ccache rewrites__FILE__. The other six failures were CPU-bound tests that timed out or aborted while parallel builds held the CPU at 100%:guest_*andaudio_out2_timing, which link libkernel, libc or libSceAudioOut but not the AGC driver. Rerun one at a time with the switch on, five of them pass;guest_pthread_start(10,000 thread starts, libkernel and libc only) timed out again under the same load.So once #6436 and #7623 are in, nothing behind #7351's AMD exclusion fails on this GPU and driver, and the exclusion could be dropped. As for caches users already have: in these runs, a run with robust2 on that started from a cache filled with it off compiled anew (0.42 s) and never failed. I can open the PR that drops the exclusion, with
Depends onboth, once they merge.MarcZX10 commentedon Oct 18, 2026
Thanks for the measurements, and for correcting the driver identification. This separates the reports into two paths: #7623 addresses the AMD proprietary driver miscompile in
subvector_loop, while #6436 addresses the GPL cache-order effect seen by the layered-volume tests. Since both PRs are still open, #7351’s AMDrobustBufferAccess2exclusion should remain until the combined changes are on main and the four reported execution tests plus the layered-volume cases are rerun on the affected AMD driver. The issue now has a concrete explanation for both failure groups; the remaining check is their combined post-merge behavior.thuanquang commentedon Oct 20, 2026
@MarcZX10 #7623 and #7828 are both on
mainnow, so I reran the cases from this issue on the RX 6700 XT (AMD's Windows driver 32.0.21045.5002) with the exclusion removed: #8267.With
robustBufferAccess2on (agc_driver_lds_lock_budgetreportsrobustBufferAccess2=1):agc_driver_layered_volume_draw,agc_driver_layered_volume_vertex,agc_driver_layered_volume_vertex_no_gplandagc_driver_subvector_looppass 3 of 3.agc_driver_subvector_loop_testspasses with libraries on then off, and off then on.#6436 is still open. With #7828 on
mainthe device is the same in both library modes, which removes the cross-mode cache effect behind the layered-volume failures, and the sequences pass without #6436. The full suite fails the same 4 tests with and without the change, and the Khronos validation layer reports noVUID-message on either side. Details are in #8267.