nir: Add a conversion and rounding intrinsic
This new intrinsic is capable of handling the full range of conversions from OpenCL including rounding modes and possible saturation. The intention is that we'll emit this intrinsic directly from spirv_to_nir and then lower it to ALU ops later. Reviewed-by: Jesse Natalie <jenatali@microsoft.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6945>
This commit is contained in:

committed by
Marge Bot

parent
0aa08ae2f6
commit
588bb6686b
@@ -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,
|
||||
|
@@ -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 *
|
||||
|
@@ -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],
|
||||
|
@@ -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? */
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user