radv: VBO range check issues with odd strides and sizes
While writing a test in vkd3d-proton (https://github.com/HansKristian-Work/vkd3d-proton/pull/723) I ran into some bugs.
Mesa: e74366b1 on RX 6800
There are two bugs:
Stride 0 case
Attribute 0 is RGBA32F at offset 16, stride = 0. VBO is bound with size = 16. We expect that all reads are OOB and return 0, but this does not happen.
if (num_records < attrib_end)
num_records = 0; /* not enough space for one vertex */ <-- Hits this case, 16 < 32
else if (stride == 0)
num_records = 1; /* only one vertex */
else
num_records = (num_records - attrib_end) / stride + 1;
if ((chip == GFX8 && num_records) || (chip >= GFX10 && !stride))
num_records = (num_records - 1) * stride + attrib_end; <-- Hits here. I think that's wrong. It should be kept at 0.
0 < Stride < 16 case
In this scenario, ACO will offset the vertex index to handle OOB correctly, but we forget to adjust the num_records to reflect this. For example, assume VBO size 36, stride = 4, attribute offset = 16.
if (num_records < attrib_end)
num_records = 0; /* not enough space for one vertex */
else if (stride == 0)
num_records = 1; /* only one vertex */
else
num_records = (num_records - attrib_end) / stride + 1; <-- Hits this case, num_records = 2 as expected
if ((chip == GFX8 && num_records) || (chip >= GFX10 && !stride))
num_records = (num_records - 1) * stride + attrib_end;
However, the vertex shader will read element 4 and 5, with offset = 0. VTX index is adjusted by offset / stride
and new offset is offset % stride
. I guess we need num_records += pipeline->attrib_index_offset[i]
to compensate, but there is no code for that right now. Alternatively, the bug might be that attrib_end doesn't reflect the adjusted offsets.
Failures:
d3d12:19885: Test failed: Test 0, index 0, 4.000000 != 0.000000
d3d12:19885: Test failed: Test 0, index 1, 5.000000 != 0.000000
d3d12:19885: Test failed: Test 0, index 2, 6.000000 != 0.000000
d3d12:19885: Test failed: Test 0, index 3, 7.000000 != 0.000000
d3d12:19886: Test failed: Test 0, index 4, 4.000000 != 0.000000
d3d12:19886: Test failed: Test 0, index 5, 5.000000 != 0.000000
d3d12:19886: Test failed: Test 0, index 6, 6.000000 != 0.000000
d3d12:19886: Test failed: Test 0, index 7, 7.000000 != 0.000000
d3d12:19885: Test failed: Test 1, index 0, 4.000000 != 0.000000
d3d12:19885: Test failed: Test 1, index 1, 5.000000 != 0.000000
d3d12:19885: Test failed: Test 1, index 2, 6.000000 != 0.000000
d3d12:19885: Test failed: Test 1, index 3, 7.000000 != 0.000000
d3d12:19886: Test failed: Test 1, index 4, 4.000000 != 0.000000
d3d12:19886: Test failed: Test 1, index 5, 5.000000 != 0.000000
d3d12:19886: Test failed: Test 1, index 6, 6.000000 != 0.000000
d3d12:19886: Test failed: Test 1, index 7, 7.000000 != 0.000000
d3d12:19885: Test failed: Test 2, index 0, 4.000000 != 0.000000
d3d12:19885: Test failed: Test 2, index 1, 5.000000 != 0.000000
d3d12:19885: Test failed: Test 2, index 2, 6.000000 != 0.000000
d3d12:19885: Test failed: Test 2, index 3, 7.000000 != 0.000000
d3d12:19886: Test failed: Test 2, index 4, 4.000000 != 0.000000
d3d12:19886: Test failed: Test 2, index 5, 5.000000 != 0.000000
d3d12:19886: Test failed: Test 2, index 6, 6.000000 != 0.000000
d3d12:19886: Test failed: Test 2, index 7, 7.000000 != 0.000000
d3d12:19885: Test failed: Test 3, index 0, 4.000000 != 0.000000
d3d12:19885: Test failed: Test 3, index 1, 5.000000 != 0.000000
d3d12:19885: Test failed: Test 3, index 2, 6.000000 != 0.000000
d3d12:19885: Test failed: Test 3, index 3, 7.000000 != 0.000000
d3d12:19886: Test failed: Test 3, index 4, 4.000000 != 0.000000
d3d12:19886: Test failed: Test 3, index 5, 5.000000 != 0.000000
d3d12:19886: Test failed: Test 3, index 6, 6.000000 != 0.000000
d3d12:19886: Test failed: Test 3, index 7, 7.000000 != 0.000000
d3d12:19885: Test failed: Test 6, index 0, 0.000000 != 4.000000
d3d12:19885: Test failed: Test 6, index 1, 0.000000 != 5.000000
d3d12:19885: Test failed: Test 6, index 2, 0.000000 != 6.000000
d3d12:19885: Test failed: Test 6, index 3, 0.000000 != 7.000000
d3d12:19886: Test failed: Test 6, index 4, 0.000000 != 5.000000
d3d12:19886: Test failed: Test 6, index 5, 0.000000 != 6.000000
d3d12:19886: Test failed: Test 6, index 6, 0.000000 != 7.000000
d3d12:19886: Test failed: Test 6, index 7, 0.000000 != 8.000000
d3d12:19885: Test failed: Test 8, index 0, 0.000000 != 4.000000
d3d12:19885: Test failed: Test 8, index 1, 0.000000 != 5.000000
d3d12:19885: Test failed: Test 8, index 2, 0.000000 != 6.000000
d3d12:19885: Test failed: Test 8, index 3, 0.000000 != 7.000000
d3d12:19886: Test failed: Test 8, index 4, 0.000000 != 6.000000
d3d12:19886: Test failed: Test 8, index 5, 0.000000 != 7.000000
d3d12:19886: Test failed: Test 8, index 6, 0.000000 != 8.000000
d3d12:19886: Test failed: Test 8, index 7, 0.000000 != 9.000000
d3d12:19886: Test failed: Test 10, index 4, 0.000000 != 7.000000
d3d12:19886: Test failed: Test 10, index 5, 0.000000 != 8.000000
d3d12:19886: Test failed: Test 10, index 6, 0.000000 != 9.000000
d3d12:19886: Test failed: Test 10, index 7, 0.000000 != 10.000000
d3d12: 115 tests executed (52 failures, 0 successful todo, 0 skipped, 0 todo, 0 bugs).