From e59ae238b606af0f3ec5c722ac2d1495caed091a Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 9 Jul 2015 10:29:18 +0200 Subject: [PATCH] nir: Implement __intrinsic_load_ssbo MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit v2: - Fix ssbo loads with boolean variables. v3: - Simplify the changes (Kristian) Reviewed-by: Connor Abbott Reviewed-by: Kristian Høgsberg --- src/glsl/nir/glsl_to_nir.cpp | 67 +++++++++++++++++++++++++ src/glsl/nir/nir_intrinsics.h | 2 +- src/glsl/nir/nir_lower_phis_to_scalar.c | 2 + 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp index d0b769a9c13..d1e2488a69e 100644 --- a/src/glsl/nir/glsl_to_nir.cpp +++ b/src/glsl/nir/glsl_to_nir.cpp @@ -651,6 +651,8 @@ nir_visitor::visit(ir_call *ir) 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"); } @@ -791,6 +793,71 @@ nir_visitor::visit(ir_call *ir) 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; + } + + break; + } default: unreachable("not reached"); } diff --git a/src/glsl/nir/nir_intrinsics.h b/src/glsl/nir/nir_intrinsics.h index d0dd7b9ee60..8cab7ea0ae0 100644 --- a/src/glsl/nir/nir_intrinsics.h +++ b/src/glsl/nir/nir_intrinsics.h @@ -200,7 +200,7 @@ SYSTEM_VALUE(user_clip_plane, 4, 1) /* const_index[0] is user_clip_plane[idx] */ LOAD(uniform, 0, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER) LOAD(ubo, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER) LOAD(input, 0, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER) -/* LOAD(ssbo, 1, 0) */ +LOAD(ssbo, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE) /* * Stores work the same way as loads, except now the first register input is diff --git a/src/glsl/nir/nir_lower_phis_to_scalar.c b/src/glsl/nir/nir_lower_phis_to_scalar.c index d72a71dfb6c..aa124d9e6cc 100644 --- a/src/glsl/nir/nir_lower_phis_to_scalar.c +++ b/src/glsl/nir/nir_lower_phis_to_scalar.c @@ -94,6 +94,8 @@ is_phi_src_scalarizable(nir_phi_src *src, case nir_intrinsic_load_uniform_indirect: case nir_intrinsic_load_ubo: case nir_intrinsic_load_ubo_indirect: + case nir_intrinsic_load_ssbo: + case nir_intrinsic_load_ssbo_indirect: case nir_intrinsic_load_input: case nir_intrinsic_load_input_indirect: return true; -- 2.30.2