From e3fcc704ab172cf2275d973c2e122d4348aaa1c1 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Fri, 17 Apr 2026 10:07:14 -0400 Subject: [PATCH] pan/nir: Lower texture queries in nir_lower_tex() on Valhall+ Reviewed-by: Lorenzo Rossi Reviewed-by: Lars-Ivar Hesselberg Simonsen Reviewed-by: Erik Faye-Lund Part-of: --- src/panfrost/ci/panfrost-g610-fails.txt | 16 ----- src/panfrost/compiler/pan_nir.h | 86 +++++++++++++++++++++++ src/panfrost/compiler/pan_nir_lower_tex.c | 43 +++++++++++- 3 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/panfrost/ci/panfrost-g610-fails.txt b/src/panfrost/ci/panfrost-g610-fails.txt index 1f16fe0ee20..65a2775e4f6 100644 --- a/src/panfrost/ci/panfrost-g610-fails.txt +++ b/src/panfrost/ci/panfrost-g610-fails.txt @@ -22,14 +22,6 @@ afbcp-spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb afbcp-spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 2d_projvec4,Fail afbcp-spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 2dshadow,Fail afbcp-spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 3d,Fail -afbcp-spec@arb_texture_query_levels@execution@fs-baselevel,Crash -afbcp-spec@arb_texture_query_levels@execution@fs-maxlevel,Crash -afbcp-spec@arb_texture_query_levels@execution@fs-miptree,Crash -afbcp-spec@arb_texture_query_levels@execution@fs-nomips,Crash -afbcp-spec@arb_texture_query_levels@execution@vs-baselevel,Crash -afbcp-spec@arb_texture_query_levels@execution@vs-maxlevel,Crash -afbcp-spec@arb_texture_query_levels@execution@vs-miptree,Crash -afbcp-spec@arb_texture_query_levels@execution@vs-nomips,Crash afbcp-spec@ext_image_dma_buf_import@ext_image_dma_buf_import-refcount-multithread,Crash afbcp-spec@glsl-1.30@execution@tex-miplevel-selection texturegrad 1darray,Fail afbcp-spec@glsl-1.30@execution@tex-miplevel-selection texturegrad 1darrayshadow,Fail @@ -98,14 +90,6 @@ spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 2d,Fai spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 2d_projvec4,Fail spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 2dshadow,Fail spec@arb_shader_texture_lod@execution@tex-miplevel-selection *projgradarb 3d,Fail -spec@arb_texture_query_levels@execution@fs-baselevel,Crash -spec@arb_texture_query_levels@execution@fs-maxlevel,Crash -spec@arb_texture_query_levels@execution@fs-miptree,Crash -spec@arb_texture_query_levels@execution@fs-nomips,Crash -spec@arb_texture_query_levels@execution@vs-baselevel,Crash -spec@arb_texture_query_levels@execution@vs-maxlevel,Crash -spec@arb_texture_query_levels@execution@vs-miptree,Crash -spec@arb_texture_query_levels@execution@vs-nomips,Crash spec@arb_transform_feedback_instanced@draw-auto instanced,Fail spec@egl 1.4@egl-ext_egl_image_storage,Fail spec@egl 1.4@eglterminate then unbind context,Fail diff --git a/src/panfrost/compiler/pan_nir.h b/src/panfrost/compiler/pan_nir.h index d4e963aef5a..3d08b41ef9e 100644 --- a/src/panfrost/compiler/pan_nir.h +++ b/src/panfrost/compiler/pan_nir.h @@ -91,6 +91,92 @@ pan_nir_load_va_buf_cvt(nir_builder *b, nir_def *handle) return cvt; } +static inline nir_def * +pan_nir_load_va_buf_size_el(nir_builder *b, nir_def *handle) +{ + nir_def *size = pan_nir_load_va_desc(b, 1, 32, handle, 1 * 4); + nir_def *stride = pan_nir_load_va_desc(b, 1, 32, handle, 4 * 4); + return nir_udiv(b, size, stride); +} + +static inline nir_def * +pan_nir_load_va_tex_size(nir_builder *b, nir_def *handle, + enum glsl_sampler_dim dim, bool is_array) +{ + nir_def *dw01 = pan_nir_load_va_desc(b, 4, 16, handle, 0); + nir_def *is_null = nir_ieq_imm(b, nir_channel(b, dw01, 0), 0); + + nir_def *size, *zero; + nir_if *nif = nir_push_if(b, nir_inot(b, is_null)); + { + nir_def *comps[4] = {}; + unsigned nr_comps = 0; + + comps[nr_comps++] = nir_channel(b, dw01, 2); + if (dim != GLSL_SAMPLER_DIM_1D) + comps[nr_comps++] = nir_channel(b, dw01, 3); + + if (dim == GLSL_SAMPLER_DIM_3D) + comps[nr_comps++] = pan_nir_load_va_desc(b, 1, 16, handle, 7 * 4); + + if (is_array) + comps[nr_comps++] = pan_nir_load_va_desc(b, 1, 16, handle, 6 * 4); + + size = nir_vec(b, comps, nr_comps); + + /* All size fields are stored minus(1) */ + size = nir_iadd_imm(b, nir_u2u32(b, size), 1); + } + nir_push_else(b, nif); + { + zero = nir_imm_zero(b, size->num_components, 32); + } + nir_pop_if(b, nif); + + return nir_if_phi(b, size, zero); +} + +static inline nir_def * +pan_nir_load_va_tex_levels(nir_builder *b, nir_def *handle) +{ + nir_def *hw0 = pan_nir_load_va_desc(b, 1, 16, handle, 0); + nir_def *is_null = nir_ieq_imm(b, hw0, 0); + nir_def *zero = nir_imm_int(b, 0); + + nir_def *levels; + nir_if *nif = nir_push_if(b, nir_inot(b, is_null)); + { + /* LOD count is stored in word2[16:20] and has a minus(1) modifier. */ + nir_def *w = pan_nir_load_va_desc(b, 1, 16, handle, 2 * 4 + 2); + levels = nir_iand_imm(b, nir_u2u32(b, w), 0x1f); + levels = nir_iadd_imm(b, levels, 1); + } + nir_pop_if(b, nif); + + return nir_if_phi(b, levels, zero); +} + +static inline nir_def * +pan_nir_load_va_tex_samples(nir_builder *b, nir_def *handle) +{ + nir_def *hw0 = pan_nir_load_va_desc(b, 1, 16, handle, 0); + nir_def *is_null = nir_ieq_imm(b, hw0, 0); + nir_def *zero = nir_imm_int(b, 0); + + nir_def *samples; + nir_if *nif = nir_push_if(b, nir_inot(b, is_null)); + { + /* Sample count is stored in word3[13:15], and has a log2 modifier. */ + nir_def *w = pan_nir_load_va_desc(b, 1, 16, handle, 3 * 4); + /* No need to mask because it's at the top of the half-word */ + samples = nir_ushr_imm(b, w, 13); + samples = nir_ishl(b, nir_imm_int(b, 1), nir_u2u32(b, samples)); + } + nir_pop_if(b, nif); + + return nir_if_phi(b, samples, zero); +} + bool pan_nir_lower_bool_to_bitsize(nir_shader *shader); bool pan_nir_lower_vertex_id(nir_shader *shader); diff --git a/src/panfrost/compiler/pan_nir_lower_tex.c b/src/panfrost/compiler/pan_nir_lower_tex.c index db248d23409..d6bb5ea8617 100644 --- a/src/panfrost/compiler/pan_nir_lower_tex.c +++ b/src/panfrost/compiler/pan_nir_lower_tex.c @@ -1014,6 +1014,41 @@ va_lower_lod(nir_builder *b, nir_tex_instr *tex, uint64_t gpu_id) return true; } +static bool +va_lower_tex_query(nir_builder *b, nir_tex_instr *tex, uint64_t gpu_id) +{ + b->cursor = nir_before_instr(&tex->instr); + struct tex_srcs srcs = steal_tex_srcs(b, tex); + + nir_def *val; + switch (tex->op) { + case nir_texop_txs: + if (tex->sampler_dim == GLSL_SAMPLER_DIM_BUF) { + val = pan_nir_load_va_buf_size_el(b, srcs.tex_h); + } else { + val = pan_nir_load_va_tex_size(b, srcs.tex_h, tex->sampler_dim, + tex->is_array); + } + break; + + case nir_texop_query_levels: + assert(tex->sampler_dim != GLSL_SAMPLER_DIM_BUF); + val = pan_nir_load_va_tex_levels(b, srcs.tex_h); + break; + + case nir_texop_texture_samples: + assert(tex->sampler_dim != GLSL_SAMPLER_DIM_BUF); + val = pan_nir_load_va_tex_samples(b, srcs.tex_h); + break; + + default: + UNREACHABLE("Unhandled Valhall texture query"); + } + + nir_def_replace(&tex->def, val); + return true; +} + static bool va_lower_tex_instr(nir_builder *b, nir_tex_instr *tex, void *cb_data) { @@ -1036,6 +1071,11 @@ va_lower_tex_instr(nir_builder *b, nir_tex_instr *tex, void *cb_data) assert(tex->sampler_dim != GLSL_SAMPLER_DIM_BUF); return va_lower_lod(b, tex, gpu_id); + case nir_texop_txs: + case nir_texop_query_levels: + case nir_texop_texture_samples: + return va_lower_tex_query(b, tex, gpu_id); + default: return false; } @@ -1046,8 +1086,7 @@ pan_nir_lower_tex(nir_shader *nir, uint64_t gpu_id) { if (pan_arch(gpu_id) >= 9) { return nir_shader_tex_pass(nir, va_lower_tex_instr, - nir_metadata_control_flow, - &gpu_id); + nir_metadata_none, &gpu_id); } else if (pan_arch(gpu_id) >= 6) { return nir_shader_tex_pass(nir, bi_lower_tex_instr, nir_metadata_control_flow,