diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 14d6950d9f6..555def78efe 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -2685,7 +2685,7 @@ intrinsic("finalize_incoming_node_payload", src_comp=[-1], dest_comp=1) # load_{tex,smp}_state_pco(array element) # 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_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) # Loads the texture/sampler metadata for a given descriptor. diff --git a/src/imagination/pco/pco_nir_tex.c b/src/imagination/pco/pco_nir_tex.c index 3e175365552..241d93930e1 100644 --- a/src/imagination/pco/pco_nir_tex.c +++ b/src/imagination/pco/pco_nir_tex.c @@ -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); } +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. * @@ -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) return lower_tex_query_basic(b, tex, tex_state); - nir_def *smp_state = nir_load_smp_state_pco(b, - ROGUE_NUM_TEXSTATE_DWORDS, - smp_elem, - .desc_set = smp_desc_set, - .binding = smp_binding); + nir_def *smp_state = + nir_load_smp_state_pco(b, + ROGUE_NUM_TEXSTATE_DWORDS, + smp_elem, + .desc_set = smp_desc_set, + .binding = smp_binding, + .flags = tex->op == nir_texop_tg4); nir_def *float_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); } + 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) { /* Set a per-pixel lod bias of 0 if none has been set yet. */ if (!lod_set) { @@ -707,13 +750,26 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data) .range = smp_data_comp_count); 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: UNREACHABLE(""); } if (tex->is_shadow) { - assert(result->num_components == 1); - nir_def *compare_op = nir_load_smp_meta_pco(b, 1, @@ -722,7 +778,7 @@ lower_tex(nir_builder *b, nir_instr *instr, UNUSED void *cb_data) .binding = smp_binding, .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; diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index b9953233ad8..2c390a1593e 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -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); } + /* 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); 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; break; + case nir_intrinsic_smp_raw_pco: + chans = 4; + sb_mode = PCO_SB_MODE_RAWDATA; + break; + case nir_intrinsic_smp_pco: /* Destination and chans should be correct. */ break; @@ -1307,6 +1318,7 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr) break; case nir_intrinsic_smp_coeffs_pco: + case nir_intrinsic_smp_raw_pco: case nir_intrinsic_smp_pco: case nir_intrinsic_smp_write_pco: instr = lower_smp(tctx, intr, &dest, src[0], src[1], src[2]); diff --git a/src/imagination/vulkan/pvr_common.h b/src/imagination/vulkan/pvr_common.h index 10b1c38e2a2..eccdf920715 100644 --- a/src/imagination/vulkan/pvr_common.h +++ b/src/imagination/vulkan/pvr_common.h @@ -202,9 +202,10 @@ static_assert(sizeof(struct pvr_buffer_descriptor) == 4 * sizeof(uint32_t), struct pvr_sampler_descriptor { uint64_t words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS]; uint32_t meta[PCO_SAMPLER_META_COUNT]; + uint64_t gather_words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS]; } PACKED; 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), "pvr_sampler_descriptor size is invalid."); @@ -223,7 +224,7 @@ struct pvr_combined_image_sampler_descriptor { } PACKED; static_assert( 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) + (PCO_IMAGE_META_COUNT + PCO_SAMPLER_META_COUNT) * sizeof(uint32_t), "pvr_combined_image_sampler_descriptor size is invalid."); diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 0085ccfcc82..114bf1956d4 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -3231,6 +3231,20 @@ VkResult pvr_CreateSampler(VkDevice _device, 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); return VK_SUCCESS;