fix(vk): draw quads with 8-bit indices on devices without index_uint8 #595
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
beanstalk: approved @ 1697603
beanstalk: approved @ 2c5a62e
beanstalk: approved @ 4fd82b7
beanstalk: approved @ 64d6d09
beanstalk: approved @ 6f91fae
beanstalk: approved @ 70a78f9
beanstalk: approved @ 8d361dc
beanstalk: approved @ 9d8356e
beanstalk: approved @ abf2227
beanstalk: approved @ d82f202
beanstalk: approved @ e5f1e40
beanstalk: approved @ ee8ab5f
ci: approved
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/macos
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
regression
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
ci: approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!595
Loading…
Reference in a new issue
No description provided.
Delete branch "jcabarca/Longshot:fix/vk-uint8-quads"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type: fix · Risk: low · Tested on: Windows, AMD Radeon RX 9070 XT · Needs: none
Why
On a GPU without
VK_EXT_index_type_uint8(dev.index_uint8false), every indexed quad draw with 8-bit indices was skipped, so those quads were not drawn. Quads never give 8-bit indices to the GPU (they are read on the CPU and drawn with 32-bit ones), so now they are drawn; no Vulkan rule was broken, this is a functional fix.How to reproduce
Seen on: not seen in the game: found by reading
draw()ingpu/vk/vk_draw.cpp; it needs a GPU withoutVK_EXT_index_type_uint8Settings and switches: defaults
Steps: on such a GPU, reach any scene that draws quads with 8-bit indices; game-free:
python -I -B tests/test_uint8_quads.pyon main (copy the test from this PR)Expected: the quads are drawn
Actual: the quads are skipped (
SKIP_HERE()); the test fails on mainWhat changed
Indexed quad draws with 8-bit indices are no longer skipped on devices without uint8 index support, because the quads path reads the indices on the CPU and draws with 32-bit ones. Every other primitive with 8-bit indices is still skipped there, as before.
draw()ingpu/vk/vk_draw.cpp: the skip of indexed draws with 8-bit indices on devices withoutindex_uint8no longer applies toNVN_DRAW_PRIMITIVE_QUADS.tests/test_uint8_quads.py(new) readsdraw()ingpu/vk/vk_draw.cppand checks that the quads path still reads 8-bit indices on the CPU into 32-bit ones and that the 8-bit skip before it leaves quads out.The bug, step by step:
draw()picks the index type fromd.itype(0 = 8-bit, 1 = 16-bit, 2 = 32-bit).if (d.indexed && d.itype == 0 && !dev.index_uint8) SKIP_HERE();dropped every indexed draw with 8-bit indices when the device has no uint8 index support, before the quads path is reached.unit = d.itype == 0 ? 1 : d.itype == 1 ? 2 : 4(one byte for 8-bit ones), writes two triangles per quad into the stream and binds them withbind_index(cmd, cur->stream, at6, VK_INDEX_TYPE_UINT32).No VUID:
VK_INDEX_TYPE_UINT8_EXTis never bound for quads, so nothing in the Vulkan spec was broken; the draw was simply lost.Before (
draw()):After:
Start reading at the 8-bit skip in
draw(), then the quads block right below it:unit = d.itype == 0 ? 1 : ...reads the indices andbind_index(..., VK_INDEX_TYPE_UINT32)binds the 32-bit ones.Measurements
Verdict: it fixes the bug:
tests/test_uint8_quads.pyfails on main and passes with this PR, in both interleaved runs.Hardware: AMD Radeon RX 9070 XT, Windows; the test itself is game-free (it reads source, it does not use the GPU); Python 3.12
Scene: none, game-free
Method:
tests/test_uint8_quads.pyfrom this PR against each side'sgpu/vk/vk_draw.cpp(a checkout of each commit, the PR's test copied into main's), 2 runs each, interleaved (main, PR, main, PR); the result is pass/fail, so the median is the result both runs gaveHow to reproduce:
python -I -B tests/test_uint8_quads.pyin a checkout of each side (copy the test into main's)5e072fc8196a9420tests/test_uint8_quads.py, run 1tests/test_uint8_quads.py, run 2What the test checks:
draw()(if (d.prim == NVN_DRAW_PRIMITIVE_QUADS) {) still exists, still reads 8-bit indices one byte each (unit = d.itype == 0 ? 1) and still bindsVK_INDEX_TYPE_UINT32; if not, it stops with "this test needs updating", since the fix relies on it.!dev.index_uint8withSKIP_HERE();) before the quads path still exists, and it excludesNVN_DRAW_PRIMITIVE_QUADS.Flags and settings
None.
Testing
Tested:
tests/test_uint8_quads.pyon main (fails) and on this branch (passes), Windows, Python 3.12.Built and played: this commit builds on Windows (llvm-mingw back end) and on Linux (
longshot_vk.so, without and with AMD FSR 4). Played on Windows, AMD Radeon RX 9070 XT: the game runs normally.Not tested: a device without
index_uint8: the RX 9070 XT has it, so in the game this path (quads with 8-bit indices on such a device) is never reached. Linux was built, not run.Must be tested: None: the RX 9070 XT cannot reach this path, and no GPU the team tests on is known to lack
VK_EXT_index_type_uint8; the game-free test covers the change.Risks
What could break: only devices without
index_uint8take the new path, and only for quads with 8-bit indices; those now go through the same quads path that 16-bit and 32-bit quads already use. Every other 8-bit index draw is skipped as before.Turning it off: revert the commit.
Compatibility: Nothing changes.
Checklist
Everyone
type(scope): description) of the status line's type.main.python -I -B tests/run_all.pypasses (any failure that also fails onmainis named). (the check that reads the changed code, on this PR, Windows:test_uint8_quads, passing; no other test references this code)third_party/untouched (a new folder with aPROVENANCE.mdinstead).When it applies
Assisted-by:/Co-Authored-By:trailers.mainand passing here.tests/that reads changed source updated in this PR, not weakened. (tests/test_uint8_quads.py, new, readsgpu/vk/vk_draw.cpp)longshot_vk.sowithout and with AMD FSR 4; the change is one Vulkan draw condition, no OS-specific code or paths)WIP: fix(vk): draw quads with 8-bit indices on devices without index_uint8to fix(vk): draw quads with 8-bit indices on devices without index_uint8Description updated to the new pull request template (#571): status line, How to reproduce, a summary first in What changed, the Verdict and Before/After columns in Measurements, Flags and settings under Measurements, Must be tested, Risks, and the Everyone / When it applies checklist. The code and the measurements are unchanged.
Edited the description: Testing now says it builds on Windows (llvm-mingw) and Linux.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.