diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-08-26 05:30:39 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-08-26 05:30:39 +0000 |
commit | 27c93456b58343162f7c4ad20ca6bea0c9a91646 (patch) | |
tree | 945c20b63e0b9975ee40f114c5312f8d8f1a2d0b /lib/mesa/src/gallium/auxiliary/nir | |
parent | 875b83a3ee95e248388fbf72271acc80f6f97987 (diff) |
Import Mesa 20.1.6
Diffstat (limited to 'lib/mesa/src/gallium/auxiliary/nir')
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.c | 368 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.h | 40 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.c | 769 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.h | 42 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/nir/tgsi_to_nir.h | 5 |
5 files changed, 1224 insertions, 0 deletions
diff --git a/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.c b/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.c new file mode 100644 index 000000000..33fdf4aee --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.c @@ -0,0 +1,368 @@ +/************************************************************************** + * + * Copyright 2019 Red Hat. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **************************************************************************/ + +/* + * NIR lowering passes to handle the draw stages for + * - pstipple + * - aaline + * - aapoint. + * + * These are all ported from the equivalent TGSI transforms. + */ + +#include "nir.h" +#include "tgsi/tgsi_from_mesa.h" +#include "nir_builder.h" + +#include "nir_draw_helpers.h" + +typedef struct { + nir_builder b; + nir_shader *shader; + bool fs_pos_is_sysval; + nir_variable *stip_tex; + nir_ssa_def *fragcoord; +} lower_pstipple; + +static nir_ssa_def * +load_frag_coord(nir_builder *b) +{ + nir_foreach_variable(var, &b->shader->inputs) { + if (var->data.location == VARYING_SLOT_POS) + return nir_load_var(b, var); + } + + nir_variable *pos = nir_variable_create(b->shader, nir_var_shader_in, + glsl_vec4_type(), NULL); + pos->data.location = VARYING_SLOT_POS; + pos->data.interpolation = INTERP_MODE_NOPERSPECTIVE; + pos->data.driver_location = b->shader->num_inputs++; + return nir_load_var(b, pos); +} + +static void +nir_lower_pstipple_block(nir_block *block, + lower_pstipple *state) +{ + nir_builder *b = &state->b; + nir_ssa_def *texcoord; + + b->cursor = nir_before_block(block); + + nir_ssa_def *div32 = nir_imm_vec2(b, 1.0/32.0, 1.0/32.0); + + nir_ssa_def *frag_coord = state->fs_pos_is_sysval ? nir_load_frag_coord(b) : load_frag_coord(b); + + texcoord = nir_fmul(b, frag_coord, div32); + + nir_tex_instr *tex = nir_tex_instr_create(b->shader, 1); + tex->op = nir_texop_tex; + tex->sampler_dim = GLSL_SAMPLER_DIM_2D; + tex->coord_components = 2; + tex->dest_type = nir_type_float; + tex->texture_index = state->stip_tex->data.binding; + tex->sampler_index = state->stip_tex->data.binding; + tex->src[0].src_type = nir_tex_src_coord; + tex->src[0].src = nir_src_for_ssa(texcoord); + nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL); + + nir_builder_instr_insert(b, &tex->instr); + + nir_ssa_def *condition = nir_f2b32(b, nir_channel(b, &tex->dest.ssa, 3)); + nir_intrinsic_instr *discard = nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if); + discard->src[0] = nir_src_for_ssa(condition); + nir_builder_instr_insert(b, &discard->instr); + b->shader->info.fs.uses_discard = true; +} + +static void +nir_lower_pstipple_impl(nir_function_impl *impl, + lower_pstipple *state) +{ + nir_builder *b = &state->b; + + nir_builder_init(b, impl); + + nir_block *start = nir_start_block(impl); + nir_lower_pstipple_block(start, state); +} + +void +nir_lower_pstipple_fs(struct nir_shader *shader, + unsigned *samplerUnitOut, + unsigned fixedUnit, + bool fs_pos_is_sysval) +{ + lower_pstipple state = { + .shader = shader, + .fs_pos_is_sysval = fs_pos_is_sysval, + }; + if (shader->info.stage != MESA_SHADER_FRAGMENT) + return; + + int binding = 0; + nir_foreach_variable(var, &shader->uniforms) { + if (glsl_type_is_sampler(var->type)) { + if (var->data.binding >= binding) + binding = var->data.binding + 1; + } + } + const struct glsl_type *sampler2D = + glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT); + + nir_variable *tex_var = nir_variable_create(shader, nir_var_uniform, sampler2D, "stipple_tex"); + tex_var->data.binding = binding; + tex_var->data.explicit_binding = true; + tex_var->data.how_declared = nir_var_hidden; + + shader->info.textures_used |= (1 << binding); + state.stip_tex = tex_var; + + nir_foreach_function(function, shader) { + if (function->impl) { + nir_lower_pstipple_impl(function->impl, &state); + } + } + *samplerUnitOut = binding; +} + +typedef struct { + nir_builder b; + nir_shader *shader; + nir_variable *line_width_input; +} lower_aaline; + +static void +nir_lower_aaline_block(nir_block *block, + lower_aaline *state) +{ + nir_builder *b = &state->b; + nir_foreach_instr(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + if (intrin->intrinsic != nir_intrinsic_store_deref) + continue; + + nir_variable *var = nir_intrinsic_get_var(intrin, 0); + if (var->data.mode != nir_var_shader_out) + continue; + if (var->data.location != FRAG_RESULT_COLOR) + continue; + + nir_ssa_def *out_input = intrin->src[1].ssa; + b->cursor = nir_before_instr(instr); + nir_ssa_def *lw = nir_load_var(b, state->line_width_input); + nir_ssa_def *tmp = nir_fsat(b, nir_fadd(b, nir_channel(b, lw, 1), + nir_fneg(b, nir_fabs(b, nir_channel(b, lw, 0))))); + nir_ssa_def *tmp1 = nir_fsat(b, nir_fadd(b, nir_channel(b, lw, 3), + nir_fneg(b, nir_fabs(b, nir_channel(b, lw, 2))))); + + tmp = nir_fmul(b, tmp, tmp1); + tmp = nir_fmul(b, nir_channel(b, out_input, 3), tmp); + + nir_ssa_def *out = nir_vec4(b, nir_channel(b, out_input, 0), + nir_channel(b, out_input, 1), + nir_channel(b, out_input, 2), + tmp); + nir_instr_rewrite_src(instr, &intrin->src[1], nir_src_for_ssa(out)); + } + +} + +static void +nir_lower_aaline_impl(nir_function_impl *impl, + lower_aaline *state) +{ + nir_builder *b = &state->b; + + nir_builder_init(b, impl); + + nir_foreach_block(block, impl) { + nir_lower_aaline_block(block, state); + } +} + +void +nir_lower_aaline_fs(struct nir_shader *shader, int *varying) +{ + lower_aaline state = { + .shader = shader, + }; + if (shader->info.stage != MESA_SHADER_FRAGMENT) + return; + + int highest_location = -1, highest_drv_location = -1; + nir_foreach_variable(var, &shader->inputs) { + if ((int)var->data.location > highest_location) + highest_location = var->data.location; + if ((int)var->data.driver_location > highest_drv_location) + highest_drv_location = var->data.driver_location; + } + + nir_variable *line_width = nir_variable_create(shader, nir_var_shader_in, + glsl_vec4_type(), "aaline"); + if (highest_location == -1 || highest_location < VARYING_SLOT_VAR0) { + line_width->data.location = VARYING_SLOT_VAR0; + line_width->data.driver_location = highest_drv_location + 1; + } else { + line_width->data.location = highest_location + 1; + line_width->data.driver_location = highest_drv_location + 1; + } + shader->num_inputs++; + *varying = tgsi_get_generic_gl_varying_index(line_width->data.location, true); + state.line_width_input = line_width; + + nir_foreach_function(function, shader) { + if (function->impl) { + nir_lower_aaline_impl(function->impl, &state); + } + } +} + +typedef struct { + nir_builder b; + nir_shader *shader; + nir_variable *input; +} lower_aapoint; + +static void +nir_lower_aapoint_block(nir_block *block, + lower_aapoint *state, nir_ssa_def *sel) +{ + nir_builder *b = &state->b; + nir_foreach_instr(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + if (intrin->intrinsic != nir_intrinsic_store_deref) + continue; + + nir_variable *var = nir_intrinsic_get_var(intrin, 0); + if (var->data.mode != nir_var_shader_out) + continue; + if (var->data.location != FRAG_RESULT_COLOR) + continue; + + nir_ssa_def *out_input = intrin->src[1].ssa; + b->cursor = nir_before_instr(instr); + + nir_ssa_def *tmp = nir_fmul(b, nir_channel(b, out_input, 3), sel); + nir_ssa_def *out = nir_vec4(b, nir_channel(b, out_input, 0), + nir_channel(b, out_input, 1), + nir_channel(b, out_input, 2), + tmp); + nir_instr_rewrite_src(instr, &intrin->src[1], nir_src_for_ssa(out)); + } + +} + +static void +nir_lower_aapoint_impl(nir_function_impl *impl, + lower_aapoint *state) +{ + nir_builder *b = &state->b; + + nir_builder_init(b, impl); + + nir_block *block = nir_start_block(impl); + b->cursor = nir_before_block(block); + + nir_ssa_def *aainput = nir_load_var(b, state->input); + + nir_ssa_def *dist = nir_fadd(b, nir_fmul(b, nir_channel(b, aainput, 0), nir_channel(b, aainput, 0)), + nir_fmul(b, nir_channel(b, aainput, 1), nir_channel(b, aainput, 1))); + + nir_ssa_def *k = nir_channel(b, aainput, 2); + nir_ssa_def *chan_val_one = nir_channel(b, aainput, 3); + nir_ssa_def *comp = nir_flt32(b, chan_val_one, dist); + + nir_intrinsic_instr *discard = nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if); + discard->src[0] = nir_src_for_ssa(comp); + nir_builder_instr_insert(b, &discard->instr); + b->shader->info.fs.uses_discard = true; + + /* compute coverage factor = (1-d)/(1-k) */ + /* 1 - k */ + nir_ssa_def *tmp = nir_fadd(b, chan_val_one, nir_fneg(b, k)); + /* 1.0 / (1 - k) */ + tmp = nir_frcp(b, tmp); + + /* 1 - d */ + nir_ssa_def *tmp2 = nir_fadd(b, chan_val_one, nir_fneg(b, dist)); + + /* (1 - d) / (1 - k) */ + nir_ssa_def *coverage = nir_fmul(b, tmp, tmp2); + + /* if (k >= distance) + * sel = coverage; + * else + * sel = 1.0; + */ + nir_ssa_def *sel = nir_b32csel(b, nir_fge32(b, k, dist), coverage, chan_val_one); + + nir_foreach_block(block, impl) { + nir_lower_aapoint_block(block, state, sel); + } +} + +void +nir_lower_aapoint_fs(struct nir_shader *shader, int *varying) +{ + lower_aapoint state = { + .shader = shader, + }; + if (shader->info.stage != MESA_SHADER_FRAGMENT) + return; + + int highest_location = -1, highest_drv_location = -1; + nir_foreach_variable(var, &shader->inputs) { + if ((int)var->data.location > highest_location) + highest_location = var->data.location; + if ((int)var->data.driver_location > highest_drv_location) + highest_drv_location = var->data.driver_location; + } + + nir_variable *aapoint_input = nir_variable_create(shader, nir_var_shader_in, + glsl_vec4_type(), "aapoint"); + if (highest_location == -1 || highest_location < VARYING_SLOT_VAR0) { + aapoint_input->data.location = VARYING_SLOT_VAR0; + } else { + aapoint_input->data.location = highest_location + 1; + } + aapoint_input->data.driver_location = highest_drv_location + 1; + + shader->num_inputs++; + *varying = tgsi_get_generic_gl_varying_index(aapoint_input->data.location, true); + state.input = aapoint_input; + + nir_foreach_function(function, shader) { + if (function->impl) { + nir_lower_aapoint_impl(function->impl, &state); + } + } +} diff --git a/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.h b/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.h new file mode 100644 index 000000000..08d163b97 --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/nir/nir_draw_helpers.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2019 Red Hat. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **************************************************************************/ + +#ifndef NIR_DRAW_HELPERS_H +#define NIR_DRAW_HELPERS_H +struct nir_shader; +void +nir_lower_pstipple_fs(struct nir_shader *shader, + unsigned *samplerUnitOut, + unsigned fixedUnit, + bool fs_pos_is_sysval); + +void +nir_lower_aaline_fs(struct nir_shader *shader, int *varying); + +void +nir_lower_aapoint_fs(struct nir_shader *shader, int *varying); +#endif diff --git a/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.c b/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.c new file mode 100644 index 000000000..cc705e758 --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.c @@ -0,0 +1,769 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This is ported mostly out of radeonsi, if we can drop TGSI, we can likely + * make a lot this go away. + */ + +#include "nir_to_tgsi_info.h" +#include "util/u_math.h" +#include "nir.h" +#include "nir_deref.h" +#include "tgsi/tgsi_scan.h" +#include "tgsi/tgsi_from_mesa.h" + +static nir_variable* tex_get_texture_var(nir_tex_instr *instr) +{ + for (unsigned i = 0; i < instr->num_srcs; i++) { + switch (instr->src[i].src_type) { + case nir_tex_src_texture_deref: + return nir_deref_instr_get_variable(nir_src_as_deref(instr->src[i].src)); + default: + break; + } + } + + return NULL; +} + +static nir_variable* intrinsic_get_var(nir_intrinsic_instr *instr) +{ + return nir_deref_instr_get_variable(nir_src_as_deref(instr->src[0])); +} + + +static void gather_usage_helper(const nir_deref_instr **deref_ptr, + unsigned location, + uint8_t mask, + uint8_t *usage_mask) +{ + for (; *deref_ptr; deref_ptr++) { + const nir_deref_instr *deref = *deref_ptr; + switch (deref->deref_type) { + case nir_deref_type_array: { + unsigned elem_size = + glsl_count_attribute_slots(deref->type, false); + if (nir_src_is_const(deref->arr.index)) { + location += elem_size * nir_src_as_uint(deref->arr.index); + } else { + unsigned array_elems = + glsl_get_length(deref_ptr[-1]->type); + for (unsigned i = 0; i < array_elems; i++) { + gather_usage_helper(deref_ptr + 1, + location + elem_size * i, + mask, usage_mask); + } + return; + } + break; + } + case nir_deref_type_struct: { + const struct glsl_type *parent_type = + deref_ptr[-1]->type; + unsigned index = deref->strct.index; + for (unsigned i = 0; i < index; i++) { + const struct glsl_type *ft = glsl_get_struct_field(parent_type, i); + location += glsl_count_attribute_slots(ft, false); + } + break; + } + default: + unreachable("Unhandled deref type in gather_components_used_helper"); + } + } + + usage_mask[location] |= mask & 0xf; + if (mask & 0xf0) + usage_mask[location + 1] |= (mask >> 4) & 0xf; +} + +static void gather_usage(const nir_deref_instr *deref, + uint8_t mask, + uint8_t *usage_mask) +{ + nir_deref_path path; + nir_deref_path_init(&path, (nir_deref_instr *)deref, NULL); + + unsigned location_frac = path.path[0]->var->data.location_frac; + if (glsl_type_is_64bit(deref->type)) { + uint8_t new_mask = 0; + for (unsigned i = 0; i < 4; i++) { + if (mask & (1 << i)) + new_mask |= 0x3 << (2 * i); + } + mask = new_mask << location_frac; + } else { + mask <<= location_frac; + mask &= 0xf; + } + + gather_usage_helper((const nir_deref_instr **)&path.path[1], + path.path[0]->var->data.driver_location, + mask, usage_mask); + + nir_deref_path_finish(&path); +} + +static void gather_intrinsic_load_deref_info(const nir_shader *nir, + const nir_intrinsic_instr *instr, + const nir_deref_instr *deref, + bool need_texcoord, + nir_variable *var, + struct tgsi_shader_info *info) +{ + assert(var && var->data.mode == nir_var_shader_in); + + if (nir->info.stage == MESA_SHADER_FRAGMENT) + gather_usage(deref, nir_ssa_def_components_read(&instr->dest.ssa), + info->input_usage_mask); + + switch (nir->info.stage) { + case MESA_SHADER_VERTEX: { + + break; + } + default: { + unsigned semantic_name, semantic_index; + tgsi_get_gl_varying_semantic(var->data.location, need_texcoord, + &semantic_name, &semantic_index); + + if (semantic_name == TGSI_SEMANTIC_COLOR) { + uint8_t mask = nir_ssa_def_components_read(&instr->dest.ssa); + info->colors_read |= mask << (semantic_index * 4); + } + if (semantic_name == TGSI_SEMANTIC_FACE) { + info->uses_frontface = true; + } + break; + } + } +} + +static void scan_instruction(const struct nir_shader *nir, + bool need_texcoord, + struct tgsi_shader_info *info, + nir_instr *instr) +{ + if (instr->type == nir_instr_type_alu) { + nir_alu_instr *alu = nir_instr_as_alu(instr); + + switch (alu->op) { + case nir_op_fddx: + case nir_op_fddy: + case nir_op_fddx_fine: + case nir_op_fddy_fine: + case nir_op_fddx_coarse: + case nir_op_fddy_coarse: + info->uses_derivatives = true; + break; + default: + break; + } + } else if (instr->type == nir_instr_type_tex) { + nir_tex_instr *tex = nir_instr_as_tex(instr); + nir_variable *texture = tex_get_texture_var(tex); + + if (!texture) { + info->samplers_declared |= + u_bit_consecutive(tex->sampler_index, 1); + } else { + if (texture->data.bindless) + info->uses_bindless_samplers = true; + } + + switch (tex->op) { + case nir_texop_tex: + case nir_texop_txb: + case nir_texop_lod: + info->uses_derivatives = true; + break; + default: + break; + } + } else if (instr->type == nir_instr_type_intrinsic) { + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + switch (intr->intrinsic) { + case nir_intrinsic_load_front_face: + info->uses_frontface = 1; + break; + case nir_intrinsic_load_instance_id: + info->uses_instanceid = 1; + break; + case nir_intrinsic_load_invocation_id: + info->uses_invocationid = true; + break; + case nir_intrinsic_load_num_work_groups: + info->uses_grid_size = true; + break; + case nir_intrinsic_load_local_group_size: + /* The block size is translated to IMM with a fixed block size. */ + if (info->properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] == 0) + info->uses_block_size = true; + break; + case nir_intrinsic_load_local_invocation_id: + case nir_intrinsic_load_work_group_id: { + unsigned mask = nir_ssa_def_components_read(&intr->dest.ssa); + while (mask) { + unsigned i = u_bit_scan(&mask); + + if (intr->intrinsic == nir_intrinsic_load_work_group_id) + info->uses_block_id[i] = true; + else + info->uses_thread_id[i] = true; + } + break; + } + case nir_intrinsic_load_vertex_id: + info->uses_vertexid = 1; + break; + case nir_intrinsic_load_vertex_id_zero_base: + info->uses_vertexid_nobase = 1; + break; + case nir_intrinsic_load_base_vertex: + info->uses_basevertex = 1; + break; + case nir_intrinsic_load_draw_id: + info->uses_drawid = 1; + break; + case nir_intrinsic_load_primitive_id: + info->uses_primid = 1; + break; + case nir_intrinsic_load_sample_mask_in: + info->reads_samplemask = true; + break; + case nir_intrinsic_load_tess_level_inner: + case nir_intrinsic_load_tess_level_outer: + info->reads_tess_factors = true; + break; + case nir_intrinsic_bindless_image_load: + info->uses_bindless_images = true; + + if (nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_BUF) + info->uses_bindless_buffer_load = true; + else + info->uses_bindless_image_load = true; + break; + case nir_intrinsic_bindless_image_size: + case nir_intrinsic_bindless_image_samples: + info->uses_bindless_images = true; + break; + case nir_intrinsic_bindless_image_store: + info->uses_bindless_images = true; + + if (nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_BUF) + info->uses_bindless_buffer_store = true; + else + info->uses_bindless_image_store = true; + + info->writes_memory = true; + break; + case nir_intrinsic_image_deref_store: + info->writes_memory = true; + break; + case nir_intrinsic_bindless_image_atomic_add: + case nir_intrinsic_bindless_image_atomic_imin: + case nir_intrinsic_bindless_image_atomic_imax: + case nir_intrinsic_bindless_image_atomic_umin: + case nir_intrinsic_bindless_image_atomic_umax: + case nir_intrinsic_bindless_image_atomic_and: + case nir_intrinsic_bindless_image_atomic_or: + case nir_intrinsic_bindless_image_atomic_xor: + case nir_intrinsic_bindless_image_atomic_exchange: + case nir_intrinsic_bindless_image_atomic_comp_swap: + info->uses_bindless_images = true; + + if (nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_BUF) + info->uses_bindless_buffer_atomic = true; + else + info->uses_bindless_image_atomic = true; + + info->writes_memory = true; + break; + case nir_intrinsic_image_deref_atomic_add: + case nir_intrinsic_image_deref_atomic_imin: + case nir_intrinsic_image_deref_atomic_imax: + case nir_intrinsic_image_deref_atomic_umin: + case nir_intrinsic_image_deref_atomic_umax: + case nir_intrinsic_image_deref_atomic_and: + case nir_intrinsic_image_deref_atomic_or: + case nir_intrinsic_image_deref_atomic_xor: + case nir_intrinsic_image_deref_atomic_exchange: + case nir_intrinsic_image_deref_atomic_comp_swap: + info->writes_memory = true; + break; + case nir_intrinsic_store_ssbo: + case nir_intrinsic_ssbo_atomic_add: + case nir_intrinsic_ssbo_atomic_imin: + case nir_intrinsic_ssbo_atomic_umin: + case nir_intrinsic_ssbo_atomic_imax: + case nir_intrinsic_ssbo_atomic_umax: + case nir_intrinsic_ssbo_atomic_and: + case nir_intrinsic_ssbo_atomic_or: + case nir_intrinsic_ssbo_atomic_xor: + case nir_intrinsic_ssbo_atomic_exchange: + case nir_intrinsic_ssbo_atomic_comp_swap: + info->writes_memory = true; + break; + case nir_intrinsic_load_deref: { + nir_variable *var = intrinsic_get_var(intr); + nir_variable_mode mode = var->data.mode; + nir_deref_instr *const deref = nir_src_as_deref(intr->src[0]); + enum glsl_base_type base_type = + glsl_get_base_type(glsl_without_array(var->type)); + + if (nir_deref_instr_has_indirect(deref)) { + if (mode == nir_var_shader_in) + info->indirect_files |= (1 << TGSI_FILE_INPUT); + } + if (mode == nir_var_shader_in) { + gather_intrinsic_load_deref_info(nir, intr, deref, need_texcoord, var, info); + + switch (var->data.interpolation) { + case INTERP_MODE_NONE: + if (glsl_base_type_is_integer(base_type)) + break; + + /* fall-through */ + case INTERP_MODE_SMOOTH: + if (var->data.sample) + info->uses_persp_sample = true; + else if (var->data.centroid) + info->uses_persp_centroid = true; + else + info->uses_persp_center = true; + break; + + case INTERP_MODE_NOPERSPECTIVE: + if (var->data.sample) + info->uses_linear_sample = true; + else if (var->data.centroid) + info->uses_linear_centroid = true; + else + info->uses_linear_center = true; + break; + } + } + break; + } + case nir_intrinsic_interp_deref_at_centroid: + case nir_intrinsic_interp_deref_at_sample: + case nir_intrinsic_interp_deref_at_offset: { + enum glsl_interp_mode interp = intrinsic_get_var(intr)->data.interpolation; + switch (interp) { + case INTERP_MODE_SMOOTH: + case INTERP_MODE_NONE: + if (intr->intrinsic == nir_intrinsic_interp_deref_at_centroid) + info->uses_persp_opcode_interp_centroid = true; + else if (intr->intrinsic == nir_intrinsic_interp_deref_at_sample) + info->uses_persp_opcode_interp_sample = true; + else + info->uses_persp_opcode_interp_offset = true; + break; + case INTERP_MODE_NOPERSPECTIVE: + if (intr->intrinsic == nir_intrinsic_interp_deref_at_centroid) + info->uses_linear_opcode_interp_centroid = true; + else if (intr->intrinsic == nir_intrinsic_interp_deref_at_sample) + info->uses_linear_opcode_interp_sample = true; + else + info->uses_linear_opcode_interp_offset = true; + break; + case INTERP_MODE_FLAT: + break; + default: + unreachable("Unsupported interpoation type"); + } + break; + } + default: + break; + } + } +} + +void nir_tgsi_scan_shader(const struct nir_shader *nir, + struct tgsi_shader_info *info, + bool need_texcoord) +{ + nir_function *func; + unsigned i; + + info->processor = pipe_shader_type_from_mesa(nir->info.stage); + info->num_tokens = 2; /* indicate that the shader is non-empty */ + info->num_instructions = 2; + + info->properties[TGSI_PROPERTY_NEXT_SHADER] = + pipe_shader_type_from_mesa(nir->info.next_stage); + + if (nir->info.stage == MESA_SHADER_VERTEX) { + info->properties[TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION] = + nir->info.vs.window_space_position; + } + + if (nir->info.stage == MESA_SHADER_TESS_CTRL) { + info->properties[TGSI_PROPERTY_TCS_VERTICES_OUT] = + nir->info.tess.tcs_vertices_out; + } + + if (nir->info.stage == MESA_SHADER_TESS_EVAL) { + if (nir->info.tess.primitive_mode == GL_ISOLINES) + info->properties[TGSI_PROPERTY_TES_PRIM_MODE] = PIPE_PRIM_LINES; + else + info->properties[TGSI_PROPERTY_TES_PRIM_MODE] = nir->info.tess.primitive_mode; + + STATIC_ASSERT((TESS_SPACING_EQUAL + 1) % 3 == PIPE_TESS_SPACING_EQUAL); + STATIC_ASSERT((TESS_SPACING_FRACTIONAL_ODD + 1) % 3 == + PIPE_TESS_SPACING_FRACTIONAL_ODD); + STATIC_ASSERT((TESS_SPACING_FRACTIONAL_EVEN + 1) % 3 == + PIPE_TESS_SPACING_FRACTIONAL_EVEN); + + info->properties[TGSI_PROPERTY_TES_SPACING] = (nir->info.tess.spacing + 1) % 3; + info->properties[TGSI_PROPERTY_TES_VERTEX_ORDER_CW] = !nir->info.tess.ccw; + info->properties[TGSI_PROPERTY_TES_POINT_MODE] = nir->info.tess.point_mode; + } + + if (nir->info.stage == MESA_SHADER_GEOMETRY) { + info->properties[TGSI_PROPERTY_GS_INPUT_PRIM] = nir->info.gs.input_primitive; + info->properties[TGSI_PROPERTY_GS_OUTPUT_PRIM] = nir->info.gs.output_primitive; + info->properties[TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES] = nir->info.gs.vertices_out; + info->properties[TGSI_PROPERTY_GS_INVOCATIONS] = nir->info.gs.invocations; + } + + if (nir->info.stage == MESA_SHADER_FRAGMENT) { + info->properties[TGSI_PROPERTY_FS_EARLY_DEPTH_STENCIL] = + nir->info.fs.early_fragment_tests | nir->info.fs.post_depth_coverage; + info->properties[TGSI_PROPERTY_FS_POST_DEPTH_COVERAGE] = nir->info.fs.post_depth_coverage; + + if (nir->info.fs.pixel_center_integer) { + info->properties[TGSI_PROPERTY_FS_COORD_PIXEL_CENTER] = + TGSI_FS_COORD_PIXEL_CENTER_INTEGER; + } + + if (nir->info.fs.depth_layout != FRAG_DEPTH_LAYOUT_NONE) { + switch (nir->info.fs.depth_layout) { + case FRAG_DEPTH_LAYOUT_ANY: + info->properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT] = TGSI_FS_DEPTH_LAYOUT_ANY; + break; + case FRAG_DEPTH_LAYOUT_GREATER: + info->properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT] = TGSI_FS_DEPTH_LAYOUT_GREATER; + break; + case FRAG_DEPTH_LAYOUT_LESS: + info->properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT] = TGSI_FS_DEPTH_LAYOUT_LESS; + break; + case FRAG_DEPTH_LAYOUT_UNCHANGED: + info->properties[TGSI_PROPERTY_FS_DEPTH_LAYOUT] = TGSI_FS_DEPTH_LAYOUT_UNCHANGED; + break; + default: + unreachable("Unknow depth layout"); + } + } + } + + if (gl_shader_stage_is_compute(nir->info.stage)) { + info->properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] = nir->info.cs.local_size[0]; + info->properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] = nir->info.cs.local_size[1]; + info->properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH] = nir->info.cs.local_size[2]; + } + + i = 0; + uint64_t processed_inputs = 0; + nir_foreach_variable(variable, &nir->inputs) { + unsigned semantic_name, semantic_index; + + const struct glsl_type *type = variable->type; + if (nir_is_per_vertex_io(variable, nir->info.stage)) { + assert(glsl_type_is_array(type)); + type = glsl_get_array_element(type); + } + + unsigned attrib_count = glsl_count_attribute_slots(type, + nir->info.stage == MESA_SHADER_VERTEX); + + i = variable->data.driver_location; + + /* Vertex shader inputs don't have semantics. The state + * tracker has already mapped them to attributes via + * variable->data.driver_location. + */ + if (nir->info.stage == MESA_SHADER_VERTEX) { + continue; + } + + for (unsigned j = 0; j < attrib_count; j++, i++) { + + if (processed_inputs & ((uint64_t)1 << i)) + continue; + + processed_inputs |= ((uint64_t)1 << i); + + tgsi_get_gl_varying_semantic(variable->data.location + j, need_texcoord, + &semantic_name, &semantic_index); + + info->input_semantic_name[i] = semantic_name; + info->input_semantic_index[i] = semantic_index; + + if (semantic_name == TGSI_SEMANTIC_PRIMID) + info->uses_primid = true; + + enum glsl_base_type base_type = + glsl_get_base_type(glsl_without_array(variable->type)); + + switch (variable->data.interpolation) { + case INTERP_MODE_NONE: + if (glsl_base_type_is_integer(base_type)) { + info->input_interpolate[i] = TGSI_INTERPOLATE_CONSTANT; + break; + } + + if (semantic_name == TGSI_SEMANTIC_COLOR) { + info->input_interpolate[i] = TGSI_INTERPOLATE_COLOR; + break; + } + /* fall-through */ + + case INTERP_MODE_SMOOTH: + assert(!glsl_base_type_is_integer(base_type)); + + info->input_interpolate[i] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + + case INTERP_MODE_NOPERSPECTIVE: + assert(!glsl_base_type_is_integer(base_type)); + + info->input_interpolate[i] = TGSI_INTERPOLATE_LINEAR; + break; + + case INTERP_MODE_FLAT: + info->input_interpolate[i] = TGSI_INTERPOLATE_CONSTANT; + break; + } + } + } + + info->num_inputs = nir->num_inputs; + info->file_max[TGSI_FILE_INPUT] = nir->num_inputs - 1; + + i = 0; + uint64_t processed_outputs = 0; + unsigned num_outputs = 0; + nir_foreach_variable(variable, &nir->outputs) { + unsigned semantic_name, semantic_index; + + i = variable->data.driver_location; + + const struct glsl_type *type = variable->type; + if (nir_is_per_vertex_io(variable, nir->info.stage)) { + assert(glsl_type_is_array(type)); + type = glsl_get_array_element(type); + } + + unsigned attrib_count = glsl_count_attribute_slots(type, false); + for (unsigned k = 0; k < attrib_count; k++, i++) { + + if (nir->info.stage == MESA_SHADER_FRAGMENT) { + tgsi_get_gl_frag_result_semantic(variable->data.location + k, + &semantic_name, &semantic_index); + + /* Adjust for dual source blending */ + if (variable->data.index > 0) { + semantic_index++; + } + } else { + tgsi_get_gl_varying_semantic(variable->data.location + k, need_texcoord, + &semantic_name, &semantic_index); + } + + unsigned num_components = 4; + unsigned vector_elements = glsl_get_vector_elements(glsl_without_array(variable->type)); + if (vector_elements) + num_components = vector_elements; + + unsigned component = variable->data.location_frac; + if (glsl_type_is_64bit(glsl_without_array(variable->type))) { + if (glsl_type_is_dual_slot(glsl_without_array(variable->type)) && k % 2) { + num_components = (num_components * 2) - 4; + component = 0; + } else { + num_components = MIN2(num_components * 2, 4); + } + } + + ubyte usagemask = 0; + for (unsigned j = component; j < num_components + component; j++) { + switch (j) { + case 0: + usagemask |= TGSI_WRITEMASK_X; + break; + case 1: + usagemask |= TGSI_WRITEMASK_Y; + break; + case 2: + usagemask |= TGSI_WRITEMASK_Z; + break; + case 3: + usagemask |= TGSI_WRITEMASK_W; + break; + default: + unreachable("error calculating component index"); + } + } + + unsigned gs_out_streams; + if (variable->data.stream & NIR_STREAM_PACKED) { + gs_out_streams = variable->data.stream & ~NIR_STREAM_PACKED; + } else { + assert(variable->data.stream < 4); + gs_out_streams = 0; + for (unsigned j = 0; j < num_components; ++j) + gs_out_streams |= variable->data.stream << (2 * (component + j)); + } + + unsigned streamx = gs_out_streams & 3; + unsigned streamy = (gs_out_streams >> 2) & 3; + unsigned streamz = (gs_out_streams >> 4) & 3; + unsigned streamw = (gs_out_streams >> 6) & 3; + + if (usagemask & TGSI_WRITEMASK_X) { + info->output_usagemask[i] |= TGSI_WRITEMASK_X; + info->output_streams[i] |= streamx; + info->num_stream_output_components[streamx]++; + } + if (usagemask & TGSI_WRITEMASK_Y) { + info->output_usagemask[i] |= TGSI_WRITEMASK_Y; + info->output_streams[i] |= streamy << 2; + info->num_stream_output_components[streamy]++; + } + if (usagemask & TGSI_WRITEMASK_Z) { + info->output_usagemask[i] |= TGSI_WRITEMASK_Z; + info->output_streams[i] |= streamz << 4; + info->num_stream_output_components[streamz]++; + } + if (usagemask & TGSI_WRITEMASK_W) { + info->output_usagemask[i] |= TGSI_WRITEMASK_W; + info->output_streams[i] |= streamw << 6; + info->num_stream_output_components[streamw]++; + } + + /* make sure we only count this location once against + * the num_outputs counter. + */ + if (processed_outputs & ((uint64_t)1 << i)) + continue; + + processed_outputs |= ((uint64_t)1 << i); + num_outputs++; + + info->output_semantic_name[i] = semantic_name; + info->output_semantic_index[i] = semantic_index; + + switch (semantic_name) { + case TGSI_SEMANTIC_PRIMID: + info->writes_primid = true; + break; + case TGSI_SEMANTIC_VIEWPORT_INDEX: + info->writes_viewport_index = true; + break; + case TGSI_SEMANTIC_LAYER: + info->writes_layer = true; + break; + case TGSI_SEMANTIC_PSIZE: + info->writes_psize = true; + break; + case TGSI_SEMANTIC_CLIPVERTEX: + info->writes_clipvertex = true; + break; + case TGSI_SEMANTIC_COLOR: + info->colors_written |= 1 << semantic_index; + break; + case TGSI_SEMANTIC_STENCIL: + info->writes_stencil = true; + break; + case TGSI_SEMANTIC_SAMPLEMASK: + info->writes_samplemask = true; + break; + case TGSI_SEMANTIC_EDGEFLAG: + info->writes_edgeflag = true; + break; + case TGSI_SEMANTIC_POSITION: + if (info->processor == PIPE_SHADER_FRAGMENT) + info->writes_z = true; + else + info->writes_position = true; + break; + } + + if (nir->info.stage == MESA_SHADER_TESS_CTRL) { + switch (semantic_name) { + case TGSI_SEMANTIC_PATCH: + info->reads_perpatch_outputs = true; + break; + case TGSI_SEMANTIC_TESSINNER: + case TGSI_SEMANTIC_TESSOUTER: + info->reads_tessfactor_outputs = true; + break; + default: + info->reads_pervertex_outputs = true; + } + } + } + + unsigned loc = variable->data.location; + if (nir->info.stage == MESA_SHADER_FRAGMENT && + loc == FRAG_RESULT_COLOR && + nir->info.outputs_written & (1ull << loc)) { + assert(attrib_count == 1); + info->properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS] = true; + } + } + + info->num_outputs = num_outputs; + + info->const_file_max[0] = nir->num_uniforms - 1; + info->const_buffers_declared = u_bit_consecutive(1, nir->info.num_ubos); + if (nir->num_uniforms > 0) + info->const_buffers_declared |= 1; + info->images_declared = u_bit_consecutive(0, nir->info.num_images); + info->samplers_declared = nir->info.textures_used; + + info->file_max[TGSI_FILE_SAMPLER] = util_last_bit(info->samplers_declared) - 1; + info->file_max[TGSI_FILE_SAMPLER_VIEW] = info->file_max[TGSI_FILE_SAMPLER]; + info->file_mask[TGSI_FILE_SAMPLER] = info->file_mask[TGSI_FILE_SAMPLER_VIEW] = info->samplers_declared; + info->file_max[TGSI_FILE_IMAGE] = util_last_bit(info->images_declared) - 1; + info->file_mask[TGSI_FILE_IMAGE] = info->images_declared; + + info->num_written_clipdistance = nir->info.clip_distance_array_size; + info->num_written_culldistance = nir->info.cull_distance_array_size; + info->clipdist_writemask = u_bit_consecutive(0, info->num_written_clipdistance); + info->culldist_writemask = u_bit_consecutive(0, info->num_written_culldistance); + + if (info->processor == PIPE_SHADER_FRAGMENT) + info->uses_kill = nir->info.fs.uses_discard; + + func = (struct nir_function *)exec_list_get_head_const(&nir->functions); + nir_foreach_block(block, func->impl) { + nir_foreach_instr(instr, block) + scan_instruction(nir, need_texcoord, info, instr); + } +} diff --git a/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.h b/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.h new file mode 100644 index 000000000..c2b8639b6 --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/nir/nir_to_tgsi_info.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _NIR_TO_TGSI_INFO_H_ +#define _NIR_TO_TGSI_INFO_H_ + +#include <stdbool.h> +struct nir_shader; +struct tgsi_shader_info; + +/* only llvmpipe uses this path, so handle draw not using llvm */ +#ifdef LLVM_AVAILABLE +void nir_tgsi_scan_shader(const struct nir_shader *nir, + struct tgsi_shader_info *info, + bool need_texcoord); +#else +static inline void nir_tgsi_scan_shader(const struct nir_shader *nir, + struct tgsi_shader_info *info, + bool need_texcoord) {} +#endif + +#endif diff --git a/lib/mesa/src/gallium/auxiliary/nir/tgsi_to_nir.h b/lib/mesa/src/gallium/auxiliary/nir/tgsi_to_nir.h index 551ee917c..666fdf5b1 100644 --- a/lib/mesa/src/gallium/auxiliary/nir/tgsi_to_nir.h +++ b/lib/mesa/src/gallium/auxiliary/nir/tgsi_to_nir.h @@ -21,6 +21,9 @@ * IN THE SOFTWARE. */ +#ifndef TGSI_TO_NIR_H +#define TGSI_TO_NIR_H + #include "compiler/nir/nir.h" #include "pipe/p_screen.h" @@ -31,3 +34,5 @@ tgsi_to_nir(const void *tgsi_tokens, struct nir_shader * tgsi_to_nir_noscreen(const void *tgsi_tokens, const nir_shader_compiler_options *options); + +#endif |