From efcb7b70504824ce8831f191ca711045f73dcf76 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 24 Nov 2020 20:55:07 +0100 Subject: [PATCH] r600/sfn: lower GS IO Signed-off-by: Gert Wollny Part-of: --- src/gallium/drivers/r600/sfn/sfn_nir.cpp | 7 + .../drivers/r600/sfn/sfn_shader_geometry.cpp | 176 ++++++++++++++---- .../drivers/r600/sfn/sfn_shader_geometry.h | 22 ++- 3 files changed, 157 insertions(+), 48 deletions(-) diff --git a/src/gallium/drivers/r600/sfn/sfn_nir.cpp b/src/gallium/drivers/r600/sfn/sfn_nir.cpp index 030a07a8db9..73ddfe7bc63 100644 --- a/src/gallium/drivers/r600/sfn/sfn_nir.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_nir.cpp @@ -847,6 +847,13 @@ int r600_shader_from_nir(struct r600_context *rctx, NIR_PASS_V(sel->nir, r600_lower_tess_io, (pipe_prim_type)key->tcs.prim_mode); } + if (sel->nir->info.stage == MESA_SHADER_GEOMETRY) { + NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_out, r600_glsl_type_size, + nir_lower_io_lower_64bit_to_32); + NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_in, r600_glsl_type_size, + nir_lower_io_lower_64bit_to_32); + } + if (sel->nir->info.stage == MESA_SHADER_TESS_CTRL || sel->nir->info.stage == MESA_SHADER_TESS_EVAL) { NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_in, r600_glsl_type_size, diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_geometry.cpp b/src/gallium/drivers/r600/sfn/sfn_shader_geometry.cpp index 58ac2700bbe..8fb23fdfbaa 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_geometry.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_shader_geometry.cpp @@ -43,9 +43,10 @@ GeometryShaderFromNir::GeometryShaderFromNir(r600_pipe_shader *sh, m_offset(0), m_next_input_ring_offset(0), m_key(key), - m_num_clip_dist(0), + m_clip_dist_mask(0), m_cur_ring_output(0), - m_gs_tri_strip_adj_fix(false) + m_gs_tri_strip_adj_fix(false), + m_input_mask(0) { sh_info().atomic_base = key.gs.first_atomic_counter; } @@ -55,26 +56,141 @@ bool GeometryShaderFromNir::do_emit_load_deref(UNUSED const nir_variable *in_var return false; } -bool GeometryShaderFromNir::do_emit_store_deref(const nir_variable *out_var, nir_intrinsic_instr* instr) +bool GeometryShaderFromNir::do_emit_store_deref(UNUSED const nir_variable *out_var, UNUSED nir_intrinsic_instr* instr) { + return false; +} + +bool GeometryShaderFromNir::emit_store(nir_intrinsic_instr* instr) +{ + auto location = nir_intrinsic_io_semantics(instr).location; + auto index = nir_src_as_const_value(instr->src[1]); + assert(index); + auto driver_location = nir_intrinsic_base(instr) + index->u32; + uint32_t write_mask = nir_intrinsic_write_mask(instr); GPRVector::Swizzle swz = swizzle_from_mask(write_mask); - auto out_value = vec_from_nir_with_fetch_constant(instr->src[1], write_mask, swz, true); - sh_info().output[out_var->data.driver_location].write_mask = write_mask; + auto out_value = vec_from_nir_with_fetch_constant(instr->src[0], write_mask, swz, true); + + sh_info().output[driver_location].write_mask = write_mask; auto ir = new MemRingOutIntruction(cf_mem_ring, mem_write_ind, out_value, - 4 * out_var->data.driver_location, + 4 * driver_location, instr->num_components, m_export_base[0]); - - streamout_data[out_var->data.location] = ir; + streamout_data[location] = ir; return true; } bool GeometryShaderFromNir::scan_sysvalue_access(UNUSED nir_instr *instr) { - return true; + if (instr->type != nir_instr_type_intrinsic) + return true; + + nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr); + + switch (ii->intrinsic) { + case nir_intrinsic_store_output: + return process_store_output(ii); + case nir_intrinsic_load_input: + case nir_intrinsic_load_per_vertex_input: + return process_load_input(ii); + default: + return true; + } +} + +bool GeometryShaderFromNir::process_store_output(nir_intrinsic_instr* instr) +{ + auto location = nir_intrinsic_io_semantics(instr).location; + auto index = nir_src_as_const_value(instr->src[1]); + assert(index); + + auto driver_location = nir_intrinsic_base(instr) + index->u32; + + if (location == VARYING_SLOT_COL0 || + location == VARYING_SLOT_COL1 || + (location >= VARYING_SLOT_VAR0 && + location <= VARYING_SLOT_VAR31) || + (location >= VARYING_SLOT_TEX0 && + location <= VARYING_SLOT_TEX7) || + location == VARYING_SLOT_BFC0 || + location == VARYING_SLOT_BFC1 || + location == VARYING_SLOT_PNTC || + location == VARYING_SLOT_CLIP_VERTEX || + location == VARYING_SLOT_CLIP_DIST0 || + location == VARYING_SLOT_CLIP_DIST1 || + location == VARYING_SLOT_PRIMITIVE_ID || + location == VARYING_SLOT_POS || + location == VARYING_SLOT_PSIZ || + location == VARYING_SLOT_LAYER || + location == VARYING_SLOT_VIEWPORT || + location == VARYING_SLOT_FOGC) { + r600_shader_io& io = sh_info().output[driver_location]; + + auto semantic = r600_get_varying_semantic(location); + io.name = semantic.first; + io.sid = semantic.second; + + evaluate_spi_sid(io); + + if (sh_info().noutput <= driver_location) + sh_info().noutput = driver_location + 1; + + if (location == VARYING_SLOT_CLIP_DIST0 || + location == VARYING_SLOT_CLIP_DIST1) { + m_clip_dist_mask |= 1 << (location - VARYING_SLOT_CLIP_DIST0); + } + + if (location == VARYING_SLOT_VIEWPORT) { + sh_info().vs_out_viewport = 1; + sh_info().vs_out_misc_write = 1; + } + return true; + } + return false; +} + +bool GeometryShaderFromNir::process_load_input(nir_intrinsic_instr* instr) +{ + auto location = nir_intrinsic_io_semantics(instr).location; + auto index = nir_src_as_const_value(instr->src[1]); + assert(index); + + auto driver_location = nir_intrinsic_base(instr) + index->u32; + + if (location == VARYING_SLOT_POS || + location == VARYING_SLOT_PSIZ || + location == VARYING_SLOT_FOGC || + location == VARYING_SLOT_CLIP_VERTEX || + location == VARYING_SLOT_CLIP_DIST0 || + location == VARYING_SLOT_CLIP_DIST1 || + location == VARYING_SLOT_COL0 || + location == VARYING_SLOT_COL1 || + location == VARYING_SLOT_BFC0 || + location == VARYING_SLOT_BFC1 || + location == VARYING_SLOT_PNTC || + (location >= VARYING_SLOT_VAR0 && + location <= VARYING_SLOT_VAR31) || + (location >= VARYING_SLOT_TEX0 && + location <= VARYING_SLOT_TEX7)) { + + uint64_t bit = 1ull << location; + if (!(bit & m_input_mask)) { + r600_shader_io& io = sh_info().input[driver_location]; + auto semantic = r600_get_varying_semantic(location); + io.name = semantic.first; + io.sid = semantic.second; + + io.ring_offset = 16 * driver_location; + ++sh_info().ninput; + m_next_input_ring_offset += 16; + m_input_mask |= bit; + } + return true; + } + return false; } bool GeometryShaderFromNir::do_process_inputs(nir_variable *input) @@ -141,7 +257,7 @@ bool GeometryShaderFromNir::do_process_outputs(nir_variable *output) if (output->data.location == VARYING_SLOT_CLIP_DIST0 || output->data.location == VARYING_SLOT_CLIP_DIST1) { - m_num_clip_dist += 4; + m_clip_dist_mask |= 1 << (output->data.location - VARYING_SLOT_CLIP_DIST0); } if (output->data.location == VARYING_SLOT_VIEWPORT) { @@ -230,31 +346,10 @@ void GeometryShaderFromNir::emit_adj_fix() m_per_vertex_offsets[i] = adjhelp[i]; } -bool GeometryShaderFromNir::emit_deref_instruction_override(nir_deref_instr* instr) -{ - if (instr->deref_type == nir_deref_type_array) { - auto var = get_deref_location(instr->parent); - ArrayDeref ad = {var, &instr->arr.index}; - assert(instr->dest.is_ssa); - m_in_array_deref[instr->dest.ssa.index] = ad; - - /* Problem: nir_intrinsice_load_deref tries to lookup the - * variable, and will not find it, need to override that too */ - return true; - } - return false; -} bool GeometryShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_instr* instr) { switch (instr->intrinsic) { - case nir_intrinsic_load_deref: { - auto& src = instr->src[0]; - assert(src.is_ssa); - auto array = m_in_array_deref.find(src.ssa->index); - if (array != m_in_array_deref.end()) - return emit_load_from_array(instr, array->second); - } break; case nir_intrinsic_emit_vertex: return emit_vertex(instr, false); case nir_intrinsic_end_primitive: @@ -263,6 +358,10 @@ bool GeometryShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_in return load_preloaded_value(instr->dest, 0, m_primitive_id); case nir_intrinsic_load_invocation_id: return load_preloaded_value(instr->dest, 0, m_invocation_id); + case nir_intrinsic_store_output: + return emit_store(instr); + case nir_intrinsic_load_per_vertex_input: + return emit_load_per_vertex_input(instr); default: ; } @@ -292,22 +391,22 @@ bool GeometryShaderFromNir::emit_vertex(nir_intrinsic_instr* instr, bool cut) return true; } -bool GeometryShaderFromNir::emit_load_from_array(nir_intrinsic_instr* instr, - const ArrayDeref& array_deref) +bool GeometryShaderFromNir::emit_load_per_vertex_input(nir_intrinsic_instr* instr) { auto dest = vec_from_nir(instr->dest, instr->num_components); - auto literal_index = nir_src_as_const_value(*array_deref.index); + auto literal_index = nir_src_as_const_value(instr->src[0]); if (!literal_index) { sfn_log << SfnLog::err << "GS: Indirect input addressing not (yet) supported\n"; return false; } assert(literal_index->u32 < 6); + assert(nir_intrinsic_io_semantics(instr).num_slots == 1); PValue addr = m_per_vertex_offsets[literal_index->u32]; auto fetch = new FetchInstruction(vc_fetch, no_index_offset, dest, addr, - 16 * array_deref.var->data.driver_location, + 16 * nir_intrinsic_base(instr), R600_GS_RING_CONST_BUFFER, PValue(), bim_none, true); emit_instruction(fetch); return true; @@ -315,9 +414,10 @@ bool GeometryShaderFromNir::emit_load_from_array(nir_intrinsic_instr* instr, void GeometryShaderFromNir::do_finalize() { - if (m_num_clip_dist) { - sh_info().cc_dist_mask = (1 << m_num_clip_dist) - 1; - sh_info().clip_dist_write = (1 << m_num_clip_dist) - 1; + if (m_clip_dist_mask) { + int num_clip_dist = 4 * util_bitcount(m_clip_dist_mask); + sh_info().cc_dist_mask = (1 << num_clip_dist) - 1; + sh_info().clip_dist_write = (1 << num_clip_dist) - 1; } } diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_geometry.h b/src/gallium/drivers/r600/sfn/sfn_shader_geometry.h index 1e0776912eb..b87bd34740d 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_geometry.h +++ b/src/gallium/drivers/r600/sfn/sfn_shader_geometry.h @@ -36,26 +36,28 @@ class GeometryShaderFromNir : public VertexStage { public: GeometryShaderFromNir(r600_pipe_shader *sh, r600_pipe_shader_selector& sel, const r600_shader_key& key, enum chip_class chip_class); - bool do_emit_load_deref(const nir_variable *in_var, nir_intrinsic_instr* instr) override; - bool do_emit_store_deref(const nir_variable *out_var, nir_intrinsic_instr* instr) override; + bool scan_sysvalue_access(nir_instr *instr) override; PValue primitive_id() override {return m_primitive_id;} private: - struct ArrayDeref { - const nir_variable *var; - const nir_src *index; - }; + bool do_emit_load_deref(const nir_variable *in_var, nir_intrinsic_instr* instr) override; + bool do_emit_store_deref(const nir_variable *out_var, nir_intrinsic_instr* instr) override; bool do_process_inputs(nir_variable *input) override; bool do_allocate_reserved_registers() override; bool do_process_outputs(nir_variable *output) override; - bool emit_deref_instruction_override(nir_deref_instr* instr) override; bool emit_intrinsic_instruction_override(nir_intrinsic_instr* instr) override; - bool emit_load_from_array(nir_intrinsic_instr* instr, const ArrayDeref& array_deref); + bool emit_vertex(nir_intrinsic_instr* instr, bool cut); void emit_adj_fix(); + bool process_store_output(nir_intrinsic_instr* instr); + bool process_load_input(nir_intrinsic_instr* instr); + + bool emit_store(nir_intrinsic_instr* instr); + bool emit_load_per_vertex_input(nir_intrinsic_instr* instr); + void do_finalize() override; r600_pipe_shader *m_pipe_shader; @@ -67,13 +69,13 @@ private: PValue m_export_base[4]; bool m_first_vertex_emitted; - std::map m_in_array_deref; int m_offset; int m_next_input_ring_offset; r600_shader_key m_key; - int m_num_clip_dist; + int m_clip_dist_mask; unsigned m_cur_ring_output; bool m_gs_tri_strip_adj_fix; + uint64_t m_input_mask; std::map streamout_data; }; -- 2.34.1