diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index b0a3da53cfb..ad96dbace24 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1736,12 +1736,12 @@ typedef enum { NIR_INTRINSIC_DESC_TYPE, /** - * The nir_alu_type of input data to a store + * The nir_alu_type of input data to a store or conversion */ NIR_INTRINSIC_SRC_TYPE, /** - * The nir_alu_type of the data output from a load + * The nir_alu_type of the data output from a load or conversion */ NIR_INTRINSIC_DEST_TYPE, @@ -1783,6 +1783,16 @@ typedef enum { */ NIR_INTRINSIC_IO_SEMANTICS, + /** + * The rounding mode of a conversion + */ + NIR_INTRINSIC_ROUNDING_MODE, + + /** + * Whether or not to saturate in conversions + */ + NIR_INTRINSIC_SATURATE, + NIR_INTRINSIC_NUM_INDEX_FLAGS, } nir_intrinsic_index_flag; @@ -1949,6 +1959,8 @@ INTRINSIC_IDX_ACCESSORS(memory_semantics, MEMORY_SEMANTICS, nir_memory_semantics INTRINSIC_IDX_ACCESSORS(memory_modes, MEMORY_MODES, nir_variable_mode) INTRINSIC_IDX_ACCESSORS(memory_scope, MEMORY_SCOPE, nir_scope) INTRINSIC_IDX_ACCESSORS(execution_scope, EXECUTION_SCOPE, nir_scope) +INTRINSIC_IDX_ACCESSORS(rounding_mode, ROUNDING_MODE, nir_rounding_mode) +INTRINSIC_IDX_ACCESSORS(saturate, SATURATE, bool) static inline void nir_intrinsic_set_align(nir_intrinsic_instr *intrin, diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index a70bb3c6dbc..2b340bac700 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -1476,6 +1476,30 @@ nir_load_reloc_const_intel(nir_builder *b, uint32_t id) return &load->dest.ssa; } +static inline nir_ssa_def * +nir_convert_alu_types(nir_builder *b, nir_ssa_def *src, + nir_alu_type src_type, nir_alu_type dest_type, + nir_rounding_mode round, bool saturate) +{ + assert(nir_alu_type_get_type_size(dest_type) != 0); + assert(nir_alu_type_get_type_size(src_type) == 0 || + nir_alu_type_get_type_size(src_type) == src->bit_size); + src_type = (nir_alu_type)(src_type | src->bit_size); + + nir_intrinsic_instr *conv = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_convert_alu_types); + conv->src[0] = nir_src_for_ssa(src); + conv->num_components = src->num_components; + nir_intrinsic_set_src_type(conv, src_type); + nir_intrinsic_set_dest_type(conv, dest_type); + nir_intrinsic_set_rounding_mode(conv, round); + nir_intrinsic_set_saturate(conv, saturate); + nir_ssa_dest_init(&conv->instr, &conv->dest, src->num_components, + nir_alu_type_get_type_size(dest_type), NULL); + nir_builder_instr_insert(b, &conv->instr); + return &conv->dest.ssa; +} + #include "nir_builder_opcodes.h" static inline nir_ssa_def * diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 257caa66e0f..957eeffcae1 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -124,9 +124,9 @@ ALIGN_MUL = "NIR_INTRINSIC_ALIGN_MUL" ALIGN_OFFSET = "NIR_INTRINSIC_ALIGN_OFFSET" # The vulkan descriptor type for vulkan_resource_index DESC_TYPE = "NIR_INTRINSIC_DESC_TYPE" -# The nir_alu_type of input data to a store +# The nir_alu_type of input data to a store or conversion SRC_TYPE = "NIR_INTRINSIC_SRC_TYPE" -# The nir_alu_type of the data output from a load +# The nir_alu_type of the data output from a load or conversion DEST_TYPE = "NIR_INTRINSIC_DEST_TYPE" # The swizzle mask for quad_swizzle_amd & masked_swizzle_amd SWIZZLE_MASK = "NIR_INTRINSIC_SWIZZLE_MASK" @@ -141,6 +141,10 @@ MEMORY_SCOPE = "NIR_INTRINSIC_MEMORY_SCOPE" # Scope of a control barrier EXECUTION_SCOPE = "NIR_INTRINSIC_EXECUTION_SCOPE" IO_SEMANTICS = "NIR_INTRINSIC_IO_SEMANTICS" +# Rounding mode for conversions +ROUNDING_MODE = "NIR_INTRINSIC_ROUNDING_MODE" +# Whether or not to saturate in conversions +SATURATE = "NIR_INTRINSIC_SATURATE" # # Possible flags: @@ -170,6 +174,10 @@ def intrinsic(name, src_comp=[], dest_comp=-1, indices=[], intrinsic("nop", flags=[CAN_ELIMINATE]) +intrinsic("convert_alu_types", dest_comp=0, src_comp=[0], + indices=[SRC_TYPE, DEST_TYPE, ROUNDING_MODE, SATURATE], + flags=[CAN_ELIMINATE, CAN_REORDER]) + intrinsic("load_param", dest_comp=0, indices=[PARAM_IDX], flags=[CAN_ELIMINATE]) intrinsic("load_deref", dest_comp=0, src_comp=[-1], diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 7ff4ef5776e..bca020c5a4c 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -846,6 +846,8 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state) [NIR_INTRINSIC_MEMORY_SCOPE] = "mem_scope", [NIR_INTRINSIC_EXECUTION_SCOPE] = "exec_scope", [NIR_INTRINSIC_IO_SEMANTICS] = "io_semantics", + [NIR_INTRINSIC_ROUNDING_MODE] = "src_type", + [NIR_INTRINSIC_SATURATE] = "src_type", }; for (unsigned idx = 1; idx < NIR_INTRINSIC_NUM_INDEX_FLAGS; idx++) { @@ -1004,6 +1006,19 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state) } break; + case NIR_INTRINSIC_ROUNDING_MODE: { + fprintf(fp, " rounding_mode="); + switch (nir_intrinsic_rounding_mode(instr)) { + case nir_rounding_mode_undef: fprintf(fp, "undef"); break; + case nir_rounding_mode_rtne: fprintf(fp, "rtne"); break; + case nir_rounding_mode_ru: fprintf(fp, "ru"); break; + case nir_rounding_mode_rd: fprintf(fp, "rd"); break; + case nir_rounding_mode_rtz: fprintf(fp, "rtz"); break; + default: fprintf(fp, "unkown"); break; + } + break; + } + default: { unsigned off = info->index_map[idx] - 1; assert(index_name[idx]); /* forgot to update index_name table? */ diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 57f7e365158..706ddd2b5b9 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -546,6 +546,16 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) unsigned dest_bit_size = 0; unsigned src_bit_sizes[NIR_INTRINSIC_MAX_INPUTS] = { 0, }; switch (instr->intrinsic) { + case nir_intrinsic_convert_alu_types: { + nir_alu_type src_type = nir_intrinsic_src_type(instr); + nir_alu_type dest_type = nir_intrinsic_dest_type(instr); + dest_bit_size = nir_alu_type_get_type_size(dest_type); + src_bit_sizes[0] = nir_alu_type_get_type_size(src_type); + validate_assert(state, dest_bit_size != 0); + validate_assert(state, src_bit_sizes[0] != 0); + break; + } + case nir_intrinsic_load_param: { unsigned param_idx = nir_intrinsic_param_idx(instr); validate_assert(state, param_idx < state->impl->function->num_params);