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