r600/sfn: Make 3vec loads skip possible moves
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_shader_tcs.cpp
1 #include "sfn_shader_tcs.h"
2 #include "sfn_instruction_gds.h"
3 #include "tgsi/tgsi_from_mesa.h"
4
5 namespace r600 {
6
7 TcsShaderFromNir::TcsShaderFromNir(r600_pipe_shader *sh,
8 r600_pipe_shader_selector& sel,
9 const r600_shader_key& key,
10 enum chip_class chip_class):
11 ShaderFromNirProcessor (PIPE_SHADER_TESS_CTRL, sel, sh->shader,
12 sh->scratch_space_needed, chip_class),
13 m_reserved_registers(0)
14 {
15 sh_info().tcs_prim_mode = key.tcs.prim_mode;
16 }
17
18 bool TcsShaderFromNir::scan_sysvalue_access(nir_instr *instr)
19 {
20 if (instr->type != nir_instr_type_intrinsic)
21 return true;
22
23 auto intr = nir_instr_as_intrinsic(instr);
24
25 switch (intr->intrinsic) {
26 case nir_intrinsic_load_primitive_id:
27 m_sv_values.set(es_primitive_id);
28 break;
29 case nir_intrinsic_load_invocation_id:
30 m_sv_values.set(es_invocation_id);
31 break;
32 case nir_intrinsic_load_tcs_rel_patch_id_r600:
33 m_sv_values.set(es_rel_patch_id);
34 break;
35 case nir_intrinsic_load_tcs_tess_factor_base_r600:
36 m_sv_values.set(es_tess_factor_base);
37 break;
38 default:
39
40 ;
41 }
42 return true;
43 }
44
45 bool TcsShaderFromNir::do_process_outputs(nir_variable *output)
46 {
47 unsigned name, sid;
48
49 tgsi_get_gl_varying_semantic(static_cast<gl_varying_slot>(output->data.location),
50 true, &name, &sid);
51
52 auto& io = sh_info().output[sh_info().noutput++];
53 io.name = name;
54 io.write_mask = ((1 << output->type->components()) - 1)
55 << output->data.location_frac;
56 return true;
57 }
58
59 bool TcsShaderFromNir::do_allocate_reserved_registers()
60 {
61 if (m_sv_values.test(es_primitive_id)) {
62 m_reserved_registers = 1;
63 auto gpr = new GPRValue(0,0);
64 gpr->set_as_input();
65 m_primitive_id.reset(gpr);
66 }
67
68 if (m_sv_values.test(es_invocation_id)) {
69 m_reserved_registers = 1;
70 auto gpr = new GPRValue(0,2);
71 gpr->set_as_input();
72 m_invocation_id.reset(gpr);
73 }
74
75 if (m_sv_values.test(es_rel_patch_id)) {
76 m_reserved_registers = 1;
77 auto gpr = new GPRValue(0,1);
78 gpr->set_as_input();
79 m_rel_patch_id.reset(gpr);
80 }
81
82 if (m_sv_values.test(es_tess_factor_base)) {
83 m_reserved_registers = 1;
84 auto gpr = new GPRValue(0,3);
85 gpr->set_as_input();
86 m_tess_factor_base.reset(gpr);
87 }
88
89 set_reserved_registers(m_reserved_registers);
90
91 return true;
92 }
93
94 bool TcsShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_instr* instr)
95 {
96 switch (instr->intrinsic) {
97 case nir_intrinsic_load_tcs_rel_patch_id_r600:
98 return load_preloaded_value(instr->dest, 0, m_rel_patch_id);
99 case nir_intrinsic_load_invocation_id:
100 return load_preloaded_value(instr->dest, 0, m_invocation_id);
101 case nir_intrinsic_load_primitive_id:
102 return load_preloaded_value(instr->dest, 0, m_primitive_id);
103 case nir_intrinsic_load_tcs_tess_factor_base_r600:
104 return load_preloaded_value(instr->dest, 0, m_tess_factor_base);
105 case nir_intrinsic_store_tf_r600:
106 return store_tess_factor(instr);
107 default:
108 return false;
109 }
110 }
111
112 bool TcsShaderFromNir::store_tess_factor(nir_intrinsic_instr* instr)
113 {
114 const GPRVector::Swizzle& swizzle = (instr->src[0].ssa->num_components == 4) ?
115 GPRVector::Swizzle({0, 1, 2, 3}) : GPRVector::Swizzle({0, 1, 7, 7});
116 auto val = vec_from_nir_with_fetch_constant(instr->src[0],
117 (1 << instr->src[0].ssa->num_components) - 1, swizzle);
118 emit_instruction(new GDSStoreTessFactor(val));
119 return true;
120 }
121
122 }