Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ build and the release notes.
| `scripts/process_heap_usage.py` | ✓ | ✓ |
| `linux/0001` … `linux/0005` (mesh shaders, half-wave subgroups, A8XX cube, bindless and IB fixes) | | ✓ |
| `lrz/0001` (A8XX LRZ flush before the next render pass) | ✓ | ✓ |
| `android/0001` (A850v2 compute 2D LOD-zero texture-size workaround) | ✓ | |

The Android A850v2 texture-size workaround is limited to chip ID `0x44051431`.
See [diagnosis and validation](tests/manual/a850-compute-texture-size.md) for its
scope and a compute probe.
| `nir/0001` (32-bit SSBO offset wrap with pre-shifted strides, UE5 Nanite) | ✓ | ✓ |
| `fdl/0001` (A8XX buffer descriptors of 2^30 elements or more) | ✓ | ✓ |
| `tu/0001` (flushes before a render pass chain split across command buffers, UE5 indirect draws) | ✓ | ✓ |
Expand Down
33 changes: 33 additions & 0 deletions patches/android/0001-tu-a850-compute-txs-resinfo.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--- a/src/freedreno/vulkan/tu_shader.cc
+++ b/src/freedreno/vulkan/tu_shader.cc
@@ -1028,6 +1028,30 @@
/* for the input attachment case: */
if (!nir_def_is_intrinsic(bindless))
tex->src[tex_src_idx].src_type = nir_tex_src_texture_offset;
+ }
+
+ /* A850v2 GETSIZE can return corrupt compute dimensions. RESINFO uses the
+ * same 2D view width/height at LOD 0, but does not minify for other LODs.
+ */
+ if (!ref && dev->physical_device->dev_id.chip_id == 0x44051431 &&
+ b->shader->info.stage == MESA_SHADER_COMPUTE &&
+ tex->op == nir_texop_txs && tex->sampler_dim == GLSL_SAMPLER_DIM_2D &&
+ !tex->is_array && tex->def.num_components == 2 &&
+ tex->def.bit_size == 32 && tex_src_idx >= 0 &&
+ tex->src[tex_src_idx].src_type == nir_tex_src_texture_handle) {
+ int lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_lod);
+ if (lod_idx >= 0 && nir_src_is_const(tex->src[lod_idx].src) &&
+ nir_src_as_uint(tex->src[lod_idx].src) == 0) {
+ gl_access_qualifier access = static_cast<gl_access_qualifier>(
+ (descriptor_valid ? ACCESS_CAN_SPECULATE : 0) |
+ (tex->texture_non_uniform ? ACCESS_NON_UNIFORM : 0));
+ nir_def *size = nir_bindless_image_size(
+ b, 2, 32, tex->src[tex_src_idx].src.ssa, nir_imm_int(b, 0),
+ .image_dim = GLSL_SAMPLER_DIM_2D, .image_array = false,
+ .access = access);
+ nir_def_replace(&tex->def, size);
+ return true;
+ }
}

if (dev->physical_device->compiler_options.enable_texel_buffer_emulation &&
5 changes: 5 additions & 0 deletions patches/series.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@
"summary": "Reset the LRZ controls after the end-of-pass LRZ flush on A8XX, as freedreno does, so a large fast-cleared LRZ buffer no longer hangs the GPU"
},
{
"file": "android/0001-tu-a850-compute-txs-resinfo.patch",
"targets": [
"android"
],
"summary": "Use RESINFO for A850v2 compute 2D LOD-zero texture sizes to fix black or fragmented LSFG frames"
"file": "nir/0001-nir-lower-explicit-io-keep-32bit-offset-wrap.patch",
"targets": [
"android",
Expand Down
17 changes: 17 additions & 0 deletions tests/manual/a850-compute-texture-size.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#version 450
layout(local_size_x=16,local_size_y=16,local_size_z=1) in;
layout(set=0,binding=1) uniform sampler s;
layout(set=0,binding=3) uniform texture2D inputFrame;
layout(set=0,binding=8,rgba8) writeonly uniform image2D outputFrame;
void main() {
ivec2 p=ivec2(gl_GlobalInvocationID.xy);
if(any(greaterThanEqual(p,ivec2(1562,720)))) return;
ivec2 q=p.y<360?textureSize(sampler2D(inputFrame,s),0):imageSize(outputFrame);
// Leave the partial final column blue; shifting a uint by 32 is undefined.
uint bit=uint(p.x/48);
if(bit>=32u) {
imageStore(outputFrame,p,vec4(0,0,1,1));
return;
}
imageStore(outputFrame,p,vec4(float((uint(q.x)>>bit)&1),float((uint(q.y)>>bit)&1),1,1));
}
84 changes: 84 additions & 0 deletions tests/manual/a850-compute-texture-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# A850v2 compute texture-size corruption

With DD-Turnip v0.3.4, DroidDeck's original LSFG 2x shaders produced alternating
normal and black frames, sometimes with fragments of the image in the top-left
corner. The workaround replaces a narrowly scoped compute texture-size query
with the existing bindless image-size lowering.

## Isolation

In the affected compute path, copying with integer-coordinate `texelFetch`
worked. Sampling with `textureLod` using coordinates divided by
`textureSize(input, 0)` reproduced the corruption. Replacing the queried size
with the known dimensions (1562 x 720) made that sampling path work.

A diagnostic encoding the integer dimensions into color bits showed that
`textureSize` returned incorrect, workgroup-dependent values, whereas
`imageSize` returned the expected dimensions. This implicates the GETSIZE query
path; it is not just a floating-point reciprocal or LSFG precision issue.
The underlying hardware/driver cause of the incorrect GETSIZE result is not
established by this test.

## Workaround scope

The Android patch applies only to chip ID `0x44051431` (A850v2), compute shaders,
non-array 2D textures, two 32-bit result components, an already lowered bindless
texture handle, and a constant LOD of zero. It preserves descriptor validity
and non-uniform access flags.

For this case, RESINFO reads the width and height already encoded for the
view's base mip. It does not perform GETSIZE's LOD minification, so the rewrite
must not be extended to nonzero or dynamic LODs. Array, cube, 3D, multisample
queries, other shader stages, and other chip IDs keep their original path.
The recipe enables this only for Android, the platform tested here.

## Manual diagnostic

[`a850-compute-texture-size.comp`](a850-compute-texture-size.comp) is the small
GLSL probe used during diagnosis, with a guard added to clear the partial
final column instead of shifting by 32. It is a shader, not a standalone Vulkan
test runner. To run it in a compute harness:

1. Create a 1562 x 720 sampled 2D image and an equally sized RGBA8 storage image,
each with a non-array 2D view. Bind a sampler at set 0/binding 1, the sampled
image at binding 3, and the output storage image at binding 8.
2. Compile as a Vulkan compute shader, for example with
`glslangValidator -V a850-compute-texture-size.comp -o query.spv`.
3. Transition the images appropriately and dispatch 98 x 45 x 1 workgroups
(local size 16 x 16). Make compute storage writes visible before reading
back or displaying the output.
4. Each 48-pixel column encodes one bit, least significant bit first. Red
represents width, green height, and blue is always one. The top half uses
`textureSize`, the bottom half `imageSize`. Both halves should encode
width 1562 (bits 1, 3, 4, 9, 10) and height 720 (bits 4, 6, 7, 9).
Pixels at x >= 1536 are blue padding.

The observed failure and success below were obtained in DroidDeck's compute
pipeline with these bindings. Reproduction in a separate harness has not
been verified; pipeline and descriptor state may matter.

## Recorded validation

- Device: Xiaomi M154FF, SM8975, Adreno 850v2 (`0x44051431`), Android 17/API 37.
- Application: DroidDeck 0.6.0 (`e9e0186`, runtime r9); original LSFG FP16, 2x.
- Baseline: DD-Turnip v0.3.4, Mesa
`e2ab6687d5ad700cc2b856af684aa014f9dae943`, recipe
`de8bba431f1c8dd96b61c403262cf74f7756ef19`.
- Build: official Android patch set plus this workaround, NDK r26d,
Android API 34 target, platform SDK 36. No experimental descriptor-cache
patch was included.
- Before: diagnostic top half had incorrect dimensions; bottom half correctly
encoded 1562 x 720. After: both halves consistently encoded 1562 x 720.
- Restored the original LSFG shaders and actual 2x generation after diagnosis.
In the subsequent 32-frame capture, the prior black corruption was absent;
the device user also confirmed normal rendering.
- Tested library SHA-256:
`c5475d61a53063c18b7eddcd535a1a2f191081269264d4578af1957a74febc4c`.
The submitted patch adds an explanatory comment to the tested code; its
executable logic is identical.

This is targeted application/device validation, not Vulkan CTS coverage.
Other GPUs, Linux, null descriptors, and nonzero view base mips have not been
tested on hardware. A separate application setting (adaptive target 60 FPS)
improved perceived input latency; that is not a driver performance result or
part of this patch.
Loading