xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_shader_tess.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2022 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "sfn_shader_tess.h"
8 
9 #include "sfn_instr_export.h"
10 #include "sfn_shader_vs.h"
11 
12 #include <sstream>
13 
14 namespace r600 {
15 
16 using std::string;
17 
TCSShader(const r600_shader_key & key)18 TCSShader::TCSShader(const r600_shader_key& key):
19     Shader("TCS", key.tcs.first_atomic_counter),
20     m_tcs_prim_mode(key.tcs.prim_mode)
21 {
22 }
23 
24 bool
do_scan_instruction(nir_instr * instr)25 TCSShader::do_scan_instruction(nir_instr *instr)
26 {
27    if (instr->type != nir_instr_type_intrinsic)
28       return false;
29 
30    nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
31 
32    switch (ii->intrinsic) {
33    case nir_intrinsic_load_primitive_id:
34       m_sv_values.set(es_primitive_id);
35       break;
36    case nir_intrinsic_load_invocation_id:
37       m_sv_values.set(es_invocation_id);
38       break;
39    case nir_intrinsic_load_tcs_rel_patch_id_r600:
40       m_sv_values.set(es_rel_patch_id);
41       break;
42    case nir_intrinsic_load_tcs_tess_factor_base_r600:
43       m_sv_values.set(es_tess_factor_base);
44       break;
45    default:
46       return false;
47       ;
48    }
49    return true;
50 }
51 
52 int
do_allocate_reserved_registers()53 TCSShader::do_allocate_reserved_registers()
54 {
55    if (m_sv_values.test(es_primitive_id)) {
56       m_primitive_id = value_factory().allocate_pinned_register(0, 0);
57    }
58 
59    if (m_sv_values.test(es_invocation_id)) {
60       m_invocation_id = value_factory().allocate_pinned_register(0, 2);
61    }
62 
63    if (m_sv_values.test(es_rel_patch_id)) {
64       m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);
65    }
66 
67    if (m_sv_values.test(es_tess_factor_base)) {
68       m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
69    }
70 
71    return value_factory().next_register_index();
72    ;
73 }
74 
75 bool
process_stage_intrinsic(nir_intrinsic_instr * instr)76 TCSShader::process_stage_intrinsic(nir_intrinsic_instr *instr)
77 {
78    switch (instr->intrinsic) {
79    case nir_intrinsic_load_tcs_rel_patch_id_r600:
80       return emit_simple_mov(instr->def, 0, m_rel_patch_id);
81    case nir_intrinsic_load_invocation_id:
82       return emit_simple_mov(instr->def, 0, m_invocation_id);
83    case nir_intrinsic_load_primitive_id:
84       return emit_simple_mov(instr->def, 0, m_primitive_id);
85    case nir_intrinsic_load_tcs_tess_factor_base_r600:
86       return emit_simple_mov(instr->def, 0, m_tess_factor_base);
87    case nir_intrinsic_store_tf_r600:
88       return store_tess_factor(instr);
89    default:
90       return false;
91    }
92 }
93 
94 bool
store_tess_factor(nir_intrinsic_instr * instr)95 TCSShader::store_tess_factor(nir_intrinsic_instr *instr)
96 {
97    auto value0 = value_factory().src_vec4(instr->src[0], pin_group, {0, 1, 7, 7});
98    emit_instruction(new WriteTFInstr(value0));
99    return true;
100 }
101 
102 void
do_get_shader_info(r600_shader * sh_info)103 TCSShader::do_get_shader_info(r600_shader *sh_info)
104 {
105    sh_info->processor_type = PIPE_SHADER_TESS_CTRL;
106    sh_info->tcs_prim_mode = m_tcs_prim_mode;
107 }
108 
109 bool
read_prop(std::istream & is)110 TCSShader::read_prop(std::istream& is)
111 {
112    string value;
113    is >> value;
114 
115    ASSERTED auto splitpos = value.find(':');
116    assert(splitpos != string::npos);
117 
118    std::istringstream ival(value);
119    string name;
120    string val;
121 
122    std::getline(ival, name, ':');
123 
124    if (name == "TCS_PRIM_MODE")
125       ival >> m_tcs_prim_mode;
126    else
127       return false;
128    return true;
129 }
130 
131 void
do_print_properties(std::ostream & os) const132 TCSShader::do_print_properties(std::ostream& os) const
133 {
134    os << "PROP TCS_PRIM_MODE:" << m_tcs_prim_mode << "\n";
135 }
136 
TESShader(const pipe_stream_output_info * so_info,const r600_shader * gs_shader,const r600_shader_key & key)137 TESShader::TESShader(const pipe_stream_output_info *so_info,
138                      const r600_shader *gs_shader,
139                      const r600_shader_key& key):
140     VertexStageShader("TES", key.tes.first_atomic_counter),
141     m_vs_as_gs_a(key.vs.as_gs_a),
142     m_tes_as_es(key.tes.as_es)
143 {
144    if (key.tes.as_es)
145       m_export_processor = new VertexExportForGS(this, gs_shader);
146    else
147       m_export_processor = new VertexExportForFs(this, so_info, key);
148 }
149 
150 bool
do_scan_instruction(nir_instr * instr)151 TESShader::do_scan_instruction(nir_instr *instr)
152 {
153    if (instr->type != nir_instr_type_intrinsic)
154       return false;
155 
156    auto intr = nir_instr_as_intrinsic(instr);
157 
158    switch (intr->intrinsic) {
159    case nir_intrinsic_load_tess_coord_xy:
160       m_sv_values.set(es_tess_coord);
161       break;
162    case nir_intrinsic_load_primitive_id:
163       m_sv_values.set(es_primitive_id);
164       break;
165    case nir_intrinsic_load_tcs_rel_patch_id_r600:
166       m_sv_values.set(es_rel_patch_id);
167       break;
168    case nir_intrinsic_store_output: {
169       int driver_location = nir_intrinsic_base(intr);
170       auto location = static_cast<gl_varying_slot>(nir_intrinsic_io_semantics(intr).location);
171       auto write_mask = nir_intrinsic_write_mask(intr);
172 
173       if (location == VARYING_SLOT_LAYER)
174          write_mask = 4;
175 
176       ShaderOutput output(driver_location, write_mask, location);
177 
178       add_output(output);
179       break;
180    }
181    default:
182       return false;
183    }
184    return true;
185 }
186 
187 int
do_allocate_reserved_registers()188 TESShader::do_allocate_reserved_registers()
189 {
190    if (m_sv_values.test(es_tess_coord)) {
191       m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
192       m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
193    }
194 
195    if (m_sv_values.test(es_rel_patch_id)) {
196       m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
197    }
198 
199    if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
200       m_primitive_id = value_factory().allocate_pinned_register(0, 3);
201    }
202    return value_factory().next_register_index();
203 }
204 
205 bool
process_stage_intrinsic(nir_intrinsic_instr * intr)206 TESShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
207 {
208    switch (intr->intrinsic) {
209    case nir_intrinsic_load_tess_coord_xy:
210       return emit_simple_mov(intr->def, 0, m_tess_coord[0], pin_none) &&
211              emit_simple_mov(intr->def, 1, m_tess_coord[1], pin_none);
212    case nir_intrinsic_load_primitive_id:
213       return emit_simple_mov(intr->def, 0, m_primitive_id);
214    case nir_intrinsic_load_tcs_rel_patch_id_r600:
215       return emit_simple_mov(intr->def, 0, m_rel_patch_id);
216    case nir_intrinsic_store_output:
217       return m_export_processor->store_output(*intr);
218    default:
219       return false;
220    }
221 }
222 
223 void
do_get_shader_info(r600_shader * sh_info)224 TESShader::do_get_shader_info(r600_shader *sh_info)
225 {
226    sh_info->processor_type = PIPE_SHADER_TESS_EVAL;
227    m_export_processor->get_shader_info(sh_info);
228 }
229 
230 void
do_finalize()231 TESShader::do_finalize()
232 {
233    m_export_processor->finalize();
234 }
235 
236 bool
read_prop(std::istream & is)237 TESShader::TESShader::read_prop(std::istream& is)
238 {
239    (void)is;
240    return true;
241 }
242 
243 void
do_print_properties(std::ostream & os) const244 TESShader::do_print_properties(std::ostream& os) const
245 {
246    (void)os;
247 }
248 
249 } // namespace r600
250