X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fnir%2Fglsl_to_nir.cpp;h=d1e2488a69ee741d6a386eafcc16a66f87cc730e;hb=e59ae238b606af0f3ec5c722ac2d1495caed091a;hp=7a20e1a36f528972eaa1b982c235a24504d1b9bb;hpb=300d72943675a49091ecb49597b56f7bdfefd22d;p=mesa.git diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp index 7a20e1a36f5..d1e2488a69e 100644 --- a/src/glsl/nir/glsl_to_nir.cpp +++ b/src/glsl/nir/glsl_to_nir.cpp @@ -26,6 +26,7 @@ */ #include "glsl_to_nir.h" +#include "nir_control_flow.h" #include "ir_visitor.h" #include "ir_hierarchical_visitor.h" #include "ir.h" @@ -43,7 +44,7 @@ namespace { class nir_visitor : public ir_visitor { public: - nir_visitor(nir_shader *shader, gl_shader_stage stage); + nir_visitor(nir_shader *shader); ~nir_visitor(); virtual void visit(ir_variable *); @@ -65,6 +66,7 @@ public: virtual void visit(ir_dereference_variable *); virtual void visit(ir_dereference_record *); virtual void visit(ir_dereference_array *); + virtual void visit(ir_barrier *); void create_function(ir_function *ir); @@ -83,7 +85,6 @@ private: bool supports_ints; nir_shader *shader; - gl_shader_stage stage; nir_function_impl *impl; exec_list *cf_node_list; nir_instr *result; /* result of the expression tree last visited */ @@ -130,21 +131,25 @@ private: nir_shader * glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options) { - nir_shader *shader = nir_shader_create(NULL, options); + nir_shader *shader = nir_shader_create(NULL, sh->Stage, options); - nir_visitor v1(shader, sh->Stage); + nir_visitor v1(shader); nir_function_visitor v2(&v1); v2.run(sh->ir); visit_exec_list(sh->ir, &v1); + nir_lower_outputs_to_temporaries(shader); + + shader->gs.vertices_out = sh->Geom.VerticesOut; + shader->gs.invocations = sh->Geom.Invocations; + return shader; } -nir_visitor::nir_visitor(nir_shader *shader, gl_shader_stage stage) +nir_visitor::nir_visitor(nir_shader *shader) { this->supports_ints = shader->options->native_integers; this->shader = shader; - this->stage = stage; this->is_global = true; this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -261,7 +266,7 @@ nir_visitor::visit(ir_variable *ir) break; case ir_var_shader_in: - if (stage == MESA_SHADER_FRAGMENT && + if (shader->stage == MESA_SHADER_FRAGMENT && ir->data.location == VARYING_SLOT_FACE) { /* For whatever reason, GLSL IR makes gl_FrontFacing an input */ var->data.location = SYSTEM_VALUE_FRONT_FACE; @@ -279,6 +284,9 @@ nir_visitor::visit(ir_variable *ir) var->data.mode = nir_var_uniform; break; + case ir_var_shader_storage: + var->data.mode = nir_var_shader_storage; + break; case ir_var_system_value: var->data.mode = nir_var_system_value; @@ -370,6 +378,7 @@ nir_visitor::visit(ir_variable *ir) break; case nir_var_uniform: + case nir_var_shader_storage: exec_list_push_tail(&shader->uniforms, &var->node); break; @@ -614,27 +623,257 @@ nir_visitor::visit(ir_call *ir) op = nir_intrinsic_atomic_counter_inc_var; } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) { op = nir_intrinsic_atomic_counter_dec_var; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) { + op = nir_intrinsic_image_load; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) { + op = nir_intrinsic_image_store; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) { + op = nir_intrinsic_image_atomic_add; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) { + op = nir_intrinsic_image_atomic_min; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) { + op = nir_intrinsic_image_atomic_max; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) { + op = nir_intrinsic_image_atomic_and; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) { + op = nir_intrinsic_image_atomic_or; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) { + op = nir_intrinsic_image_atomic_xor; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) { + op = nir_intrinsic_image_atomic_exchange; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) { + op = nir_intrinsic_image_atomic_comp_swap; + } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) { + op = nir_intrinsic_memory_barrier; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_size") == 0) { + op = nir_intrinsic_image_size; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_samples") == 0) { + op = nir_intrinsic_image_samples; + } else if (strcmp(ir->callee_name(), "__intrinsic_store_ssbo") == 0) { + op = nir_intrinsic_store_ssbo; + } else if (strcmp(ir->callee_name(), "__intrinsic_load_ssbo") == 0) { + op = nir_intrinsic_load_ssbo; } else { unreachable("not reached"); } nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op); - ir_dereference *param = - (ir_dereference *) ir->actual_parameters.get_head(); - instr->variables[0] = evaluate_deref(&instr->instr, param); - nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL); + nir_dest *dest = &instr->dest; + + switch (op) { + case nir_intrinsic_atomic_counter_read_var: + case nir_intrinsic_atomic_counter_inc_var: + case nir_intrinsic_atomic_counter_dec_var: { + ir_dereference *param = + (ir_dereference *) ir->actual_parameters.get_head(); + instr->variables[0] = evaluate_deref(&instr->instr, param); + nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL); + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + } + case nir_intrinsic_image_load: + case nir_intrinsic_image_store: + case nir_intrinsic_image_atomic_add: + case nir_intrinsic_image_atomic_min: + case nir_intrinsic_image_atomic_max: + case nir_intrinsic_image_atomic_and: + case nir_intrinsic_image_atomic_or: + case nir_intrinsic_image_atomic_xor: + case nir_intrinsic_image_atomic_exchange: + case nir_intrinsic_image_atomic_comp_swap: + case nir_intrinsic_image_samples: + case nir_intrinsic_image_size: { + nir_ssa_undef_instr *instr_undef = + nir_ssa_undef_instr_create(shader, 1); + nir_instr_insert_after_cf_list(this->cf_node_list, + &instr_undef->instr); + + /* Set the image variable dereference. */ + exec_node *param = ir->actual_parameters.get_head(); + ir_dereference *image = (ir_dereference *)param; + const glsl_type *type = + image->variable_referenced()->type->without_array(); + + instr->variables[0] = evaluate_deref(&instr->instr, image); + param = param->get_next(); + + /* Set the intrinsic destination. */ + if (ir->return_deref) { + const nir_intrinsic_info *info = + &nir_intrinsic_infos[instr->intrinsic]; + nir_ssa_dest_init(&instr->instr, &instr->dest, + info->dest_components, NULL); + } + + if (op == nir_intrinsic_image_size || + op == nir_intrinsic_image_samples) { + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + } + + /* Set the address argument, extending the coordinate vector to four + * components. + */ + const nir_src src_addr = evaluate_rvalue((ir_dereference *)param); + nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4); + nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL); + + for (int i = 0; i < 4; i++) { + if (i < type->coordinate_components()) { + instr_addr->src[i].src = src_addr; + instr_addr->src[i].swizzle[0] = i; + } else { + instr_addr->src[i].src = nir_src_for_ssa(&instr_undef->def); + } + } + + nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr); + instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa); + param = param->get_next(); + + /* Set the sample argument, which is undefined for single-sample + * images. + */ + if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) { + instr->src[1] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } else { + instr->src[1] = nir_src_for_ssa(&instr_undef->def); + } + + /* Set the intrinsic parameters. */ + if (!param->is_tail_sentinel()) { + instr->src[2] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } + + if (!param->is_tail_sentinel()) { + instr->src[3] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + } + case nir_intrinsic_memory_barrier: + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + case nir_intrinsic_store_ssbo: { + exec_node *param = ir->actual_parameters.get_head(); + ir_rvalue *block = ((ir_instruction *)param)->as_rvalue(); + + param = param->get_next(); + ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue(); + + param = param->get_next(); + ir_rvalue *val = ((ir_instruction *)param)->as_rvalue(); + + param = param->get_next(); + ir_constant *write_mask = ((ir_instruction *)param)->as_constant(); + assert(write_mask); + + /* Check if we need the indirect version */ + ir_constant *const_offset = offset->as_constant(); + if (!const_offset) { + op = nir_intrinsic_store_ssbo_indirect; + ralloc_free(instr); + instr = nir_intrinsic_instr_create(shader, op); + instr->src[2] = evaluate_rvalue(offset); + instr->const_index[0] = 0; + dest = &instr->dest; + } else { + instr->const_index[0] = const_offset->value.u[0]; + } + + instr->const_index[1] = write_mask->value.u[0]; + + instr->src[0] = evaluate_rvalue(val); + instr->num_components = val->type->vector_elements; + + instr->src[1] = evaluate_rvalue(block); + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + } + case nir_intrinsic_load_ssbo: { + exec_node *param = ir->actual_parameters.get_head(); + ir_rvalue *block = ((ir_instruction *)param)->as_rvalue(); + + param = param->get_next(); + ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue(); + + /* Check if we need the indirect version */ + ir_constant *const_offset = offset->as_constant(); + if (!const_offset) { + op = nir_intrinsic_load_ssbo_indirect; + ralloc_free(instr); + instr = nir_intrinsic_instr_create(shader, op); + instr->src[1] = evaluate_rvalue(offset); + instr->const_index[0] = 0; + dest = &instr->dest; + } else { + instr->const_index[0] = const_offset->value.u[0]; + } + + instr->src[0] = evaluate_rvalue(block); + + const glsl_type *type = ir->return_deref->var->type; + instr->num_components = type->vector_elements; + + /* Setup destination register */ + nir_ssa_dest_init(&instr->instr, &instr->dest, + type->vector_elements, NULL); + + /* Insert the created nir instruction now since in the case of boolean + * result we will need to emit another instruction after it + */ + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + + /* + * In SSBO/UBO's, a true boolean value is any non-zero value, but we + * consider a true boolean to be ~0. Fix this up with a != 0 + * comparison. + */ + if (type->base_type == GLSL_TYPE_BOOL) { + nir_load_const_instr *const_zero = + nir_load_const_instr_create(shader, 1); + const_zero->value.u[0] = 0; + nir_instr_insert_after_cf_list(this->cf_node_list, + &const_zero->instr); + + nir_alu_instr *load_ssbo_compare = + nir_alu_instr_create(shader, nir_op_ine); + load_ssbo_compare->src[0].src.is_ssa = true; + load_ssbo_compare->src[0].src.ssa = &instr->dest.ssa; + load_ssbo_compare->src[1].src.is_ssa = true; + load_ssbo_compare->src[1].src.ssa = &const_zero->def; + for (unsigned i = 0; i < type->vector_elements; i++) + load_ssbo_compare->src[1].swizzle[i] = 0; + nir_ssa_dest_init(&load_ssbo_compare->instr, + &load_ssbo_compare->dest.dest, + type->vector_elements, NULL); + load_ssbo_compare->dest.write_mask = (1 << type->vector_elements) - 1; + nir_instr_insert_after_cf_list(this->cf_node_list, + &load_ssbo_compare->instr); + dest = &load_ssbo_compare->dest.dest; + } - nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); + break; + } + default: + unreachable("not reached"); + } - nir_intrinsic_instr *store_instr = - nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); - store_instr->num_components = 1; + if (ir->return_deref) { + nir_intrinsic_instr *store_instr = + nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); + store_instr->num_components = ir->return_deref->type->vector_elements; - store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref); - store_instr->src[0].is_ssa = true; - store_instr->src[0].ssa = &instr->dest.ssa; + store_instr->variables[0] = + evaluate_deref(&store_instr->instr, ir->return_deref); + store_instr->src[0] = nir_src_for_ssa(&dest->ssa); - nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr); + nir_instr_insert_after_cf_list(this->cf_node_list, + &store_instr->instr); + } return; } @@ -822,13 +1061,9 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir) } nir_dest *dest = get_instr_dest(this->result); - assert(dest->is_ssa); - nir_src src = NIR_SRC_INIT; - src.is_ssa = true; - src.ssa = &dest->ssa; - return src; + return nir_src_for_ssa(&dest->ssa); } nir_alu_instr * @@ -884,7 +1119,6 @@ nir_visitor::visit(ir_expression *ir) nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op); load->num_components = ir->type->vector_elements; load->const_index[0] = const_index ? const_index->value.u[0] : 0; /* base offset */ - load->const_index[1] = 1; /* number of vec4's */ load->src[0] = evaluate_rvalue(ir->operands[0]); if (!const_index) load->src[1] = evaluate_rvalue(ir->operands[1]); @@ -1062,6 +1296,7 @@ nir_visitor::visit(ir_expression *ir) case ir_unop_bitcast_f2i: case ir_unop_bitcast_u2f: case ir_unop_bitcast_f2u: + case ir_unop_subroutine_to_int: /* no-op */ emit(nir_op_imov, dest_size, srcs); break; @@ -1196,6 +1431,16 @@ nir_visitor::visit(ir_expression *ir) unreachable("not reached"); } break; + case ir_unop_get_buffer_size: { + nir_intrinsic_instr *load = nir_intrinsic_instr_create( + this->shader, + nir_intrinsic_get_buffer_size); + load->num_components = ir->type->vector_elements; + load->src[0] = evaluate_rvalue(ir->operands[0]); + add_instr(&load->instr, ir->type->vector_elements); + return; + } + case ir_binop_add: case ir_binop_sub: case ir_binop_mul: @@ -1599,6 +1844,11 @@ nir_visitor::visit(ir_texture *ir) num_srcs = 0; break; + case ir_texture_samples: + op = nir_texop_texture_samples; + num_srcs = 0; + break; + default: unreachable("not reached"); } @@ -1785,3 +2035,11 @@ nir_visitor::visit(ir_dereference_array *ir) ralloc_steal(this->deref_tail, deref); this->deref_tail = &deref->deref; } + +void +nir_visitor::visit(ir_barrier *ir) +{ + nir_intrinsic_instr *instr = + nir_intrinsic_instr_create(this->shader, nir_intrinsic_barrier); + nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); +}