pvr, pco: initial texture gather support with gather sampler

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36412>
This commit is contained in:
Simon Perretta 2025-02-04 20:37:20 +00:00 committed by Marge Bot
parent ac41e9dd18
commit 46c9239c11
5 changed files with 94 additions and 11 deletions

View file

@ -2685,7 +2685,7 @@ intrinsic("finalize_incoming_node_payload", src_comp=[-1], dest_comp=1)
# load_{tex,smp}_state_pco(array element) # load_{tex,smp}_state_pco(array element)
# Loads the texture/sampler state words for a given descriptor. # Loads the texture/sampler state words for a given descriptor.
intrinsic("load_tex_state_pco", src_comp=[1], dest_comp=0, indices=[DESC_SET, BINDING, COMPONENT], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32]) intrinsic("load_tex_state_pco", src_comp=[1], dest_comp=0, indices=[DESC_SET, BINDING, COMPONENT], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32])
intrinsic("load_smp_state_pco", src_comp=[1], dest_comp=0, indices=[DESC_SET, BINDING, COMPONENT], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32]) intrinsic("load_smp_state_pco", src_comp=[1], dest_comp=0, indices=[DESC_SET, BINDING, COMPONENT, FLAGS], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32])
# load_{tex,smp}_meta_pco(array element) # load_{tex,smp}_meta_pco(array element)
# Loads the texture/sampler metadata for a given descriptor. # Loads the texture/sampler metadata for a given descriptor.

View file

@ -408,6 +408,39 @@ nir_intrinsic_instr *pco_emit_nir_smp(nir_builder *b, pco_smp_params *params)
return nir_instr_as_intrinsic(def->parent_instr); return nir_instr_as_intrinsic(def->parent_instr);
} }
static nir_def *
lower_tex_gather(nir_builder *b, nir_tex_instr *tex, nir_def *raw_data)
{
unsigned swiz[ARRAY_SIZE(tex->tg4_offsets)];
for (unsigned u = 0; u < ARRAY_SIZE(tex->tg4_offsets); ++u) {
unsigned offset = ARRAY_SIZE(*tex->tg4_offsets) * tex->tg4_offsets[u][0];
offset += tex->tg4_offsets[u][1];
offset *= ARRAY_SIZE(tex->tg4_offsets);
offset += tex->component;
swiz[u] = offset;
}
nir_def *result = nir_swizzle(b, raw_data, swiz, ARRAY_SIZE(swiz));
return result;
}
static nir_def *lower_tex_shadow(nir_builder *b,
nir_def *data,
nir_def *comparator,
nir_def *compare_op)
{
nir_def *result_comps[NIR_MAX_VEC_COMPONENTS];
for (unsigned u = 0; u < data->num_components; ++u) {
result_comps[u] =
nir_alphatst_pco(b, nir_channel(b, data, u), comparator, compare_op);
}
return nir_vec(b, result_comps, data->num_components);
}
/** /**
* \brief Lowers a texture instruction. * \brief Lowers a texture instruction.
* *
@ -469,11 +502,13 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data)
if (nir_tex_instr_is_query(tex) && tex->op != nir_texop_lod) if (nir_tex_instr_is_query(tex) && tex->op != nir_texop_lod)
return lower_tex_query_basic(b, tex, tex_state); return lower_tex_query_basic(b, tex, tex_state);
nir_def *smp_state = nir_load_smp_state_pco(b, nir_def *smp_state =
nir_load_smp_state_pco(b,
ROGUE_NUM_TEXSTATE_DWORDS, ROGUE_NUM_TEXSTATE_DWORDS,
smp_elem, smp_elem,
.desc_set = smp_desc_set, .desc_set = smp_desc_set,
.binding = smp_binding); .binding = smp_binding,
.flags = tex->op == nir_texop_tg4);
nir_def *float_coords; nir_def *float_coords;
nir_def *int_coords; nir_def *int_coords;
@ -571,6 +606,14 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data)
BITSET_CLEAR(tex_src_set, nir_tex_src_ddy); BITSET_CLEAR(tex_src_set, nir_tex_src_ddy);
} }
if (tex->op == nir_texop_tg4) {
assert(!lod_set);
smp_data_comps[smp_data_comp_count++] = nir_imm_int(b, 0);
smp_flags.pplod = true;
smp_flags.lod_mode = PCO_LOD_MODE_REPLACE;
lod_set = true;
}
if (!hw_array_support && int_array_index) { if (!hw_array_support && int_array_index) {
/* Set a per-pixel lod bias of 0 if none has been set yet. */ /* Set a per-pixel lod bias of 0 if none has been set yet. */
if (!lod_set) { if (!lod_set) {
@ -707,13 +750,26 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data)
.range = smp_data_comp_count); .range = smp_data_comp_count);
break; break;
case nir_texop_tg4:
smp_flags.integer = use_int_coords;
smp_flags.fcnorm = nir_alu_type_get_base_type(tex->dest_type) ==
nir_type_float;
result = nir_smp_raw_pco(b,
smp_data,
tex_state,
smp_state,
.smp_flags_pco = smp_flags._,
.range = smp_data_comp_count);
result = lower_tex_gather(b, tex, result);
break;
default: default:
UNREACHABLE(""); UNREACHABLE("");
} }
if (tex->is_shadow) { if (tex->is_shadow) {
assert(result->num_components == 1);
nir_def *compare_op = nir_def *compare_op =
nir_load_smp_meta_pco(b, nir_load_smp_meta_pco(b,
1, 1,
@ -722,7 +778,7 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data)
.binding = smp_binding, .binding = smp_binding,
.component = PCO_SAMPLER_META_COMPARE_OP); .component = PCO_SAMPLER_META_COMPARE_OP);
result = nir_alphatst_pco(b, result, comparator, compare_op); result = lower_tex_shadow(b, result, comparator, compare_op);
} }
return result; return result;

View file

@ -961,6 +961,12 @@ static pco_instr *lower_load_tex_smp_state(trans_ctx *tctx,
state_words = pco_ref_offset(state_words, PCO_IMAGE_META_COUNT); state_words = pco_ref_offset(state_words, PCO_IMAGE_META_COUNT);
} }
/* Gather sampler words come after standard sampler state and metadata. */
if (smp && nir_intrinsic_flags(intr)) {
state_words = pco_ref_offset(state_words, ROGUE_NUM_TEXSTATE_DWORDS);
state_words = pco_ref_offset(state_words, PCO_SAMPLER_META_COUNT);
}
state_words = pco_ref_offset(state_words, start_comp); state_words = pco_ref_offset(state_words, start_comp);
return pco_mov(&tctx->b, dest, state_words, .rpt = chans); return pco_mov(&tctx->b, dest, state_words, .rpt = chans);
@ -1022,6 +1028,11 @@ static pco_instr *lower_smp(trans_ctx *tctx,
sb_mode = PCO_SB_MODE_COEFFS; sb_mode = PCO_SB_MODE_COEFFS;
break; break;
case nir_intrinsic_smp_raw_pco:
chans = 4;
sb_mode = PCO_SB_MODE_RAWDATA;
break;
case nir_intrinsic_smp_pco: case nir_intrinsic_smp_pco:
/* Destination and chans should be correct. */ /* Destination and chans should be correct. */
break; break;
@ -1307,6 +1318,7 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr)
break; break;
case nir_intrinsic_smp_coeffs_pco: case nir_intrinsic_smp_coeffs_pco:
case nir_intrinsic_smp_raw_pco:
case nir_intrinsic_smp_pco: case nir_intrinsic_smp_pco:
case nir_intrinsic_smp_write_pco: case nir_intrinsic_smp_write_pco:
instr = lower_smp(tctx, intr, &dest, src[0], src[1], src[2]); instr = lower_smp(tctx, intr, &dest, src[0], src[1], src[2]);

View file

@ -202,9 +202,10 @@ static_assert(sizeof(struct pvr_buffer_descriptor) == 4 * sizeof(uint32_t),
struct pvr_sampler_descriptor { struct pvr_sampler_descriptor {
uint64_t words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS]; uint64_t words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS];
uint32_t meta[PCO_SAMPLER_META_COUNT]; uint32_t meta[PCO_SAMPLER_META_COUNT];
uint64_t gather_words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS];
} PACKED; } PACKED;
static_assert(sizeof(struct pvr_sampler_descriptor) == static_assert(sizeof(struct pvr_sampler_descriptor) ==
ROGUE_NUM_TEXSTATE_SAMPLER_WORDS * sizeof(uint64_t) + ROGUE_NUM_TEXSTATE_SAMPLER_WORDS * sizeof(uint64_t) * 2 +
PCO_SAMPLER_META_COUNT * sizeof(uint32_t), PCO_SAMPLER_META_COUNT * sizeof(uint32_t),
"pvr_sampler_descriptor size is invalid."); "pvr_sampler_descriptor size is invalid.");
@ -223,7 +224,7 @@ struct pvr_combined_image_sampler_descriptor {
} PACKED; } PACKED;
static_assert( static_assert(
sizeof(struct pvr_combined_image_sampler_descriptor) == sizeof(struct pvr_combined_image_sampler_descriptor) ==
(ROGUE_NUM_TEXSTATE_IMAGE_WORDS + ROGUE_NUM_TEXSTATE_SAMPLER_WORDS) * (ROGUE_NUM_TEXSTATE_IMAGE_WORDS + ROGUE_NUM_TEXSTATE_SAMPLER_WORDS * 2) *
sizeof(uint64_t) + sizeof(uint64_t) +
(PCO_IMAGE_META_COUNT + PCO_SAMPLER_META_COUNT) * sizeof(uint32_t), (PCO_IMAGE_META_COUNT + PCO_SAMPLER_META_COUNT) * sizeof(uint32_t),
"pvr_combined_image_sampler_descriptor size is invalid."); "pvr_combined_image_sampler_descriptor size is invalid.");

View file

@ -3231,6 +3231,20 @@ VkResult pvr_CreateSampler(VkDevice _device,
pvr_csb_pack (&sampler->descriptor.words[1], TEXSTATE_SAMPLER_WORD1, word) { pvr_csb_pack (&sampler->descriptor.words[1], TEXSTATE_SAMPLER_WORD1, word) {
} }
/* Setup gather sampler. */
struct ROGUE_TEXSTATE_SAMPLER_WORD0 word0;
ROGUE_TEXSTATE_SAMPLER_WORD0_unpack(&sampler->descriptor.words[0], &word0);
word0.mipfilter = false;
word0.minfilter = ROGUE_TEXSTATE_FILTER_LINEAR;
word0.magfilter = ROGUE_TEXSTATE_FILTER_LINEAR;
ROGUE_TEXSTATE_SAMPLER_WORD0_pack(&sampler->descriptor.gather_words[0],
&word0);
memcpy(&sampler->descriptor.gather_words[1],
&sampler->descriptor.words[1],
sizeof(sampler->descriptor.words[1]));
*pSampler = pvr_sampler_to_handle(sampler); *pSampler = pvr_sampler_to_handle(sampler);
return VK_SUCCESS; return VK_SUCCESS;