• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "sfn_instr_export.h"
28 #include "sfn_shader_tess.h"
29 #include "sfn_shader_vs.h"
30 
31 
32 #include <sstream>
33 
34 namespace r600 {
35 
36 using std::string;
37 
TCSShader(const r600_shader_key & key)38 TCSShader::TCSShader(const r600_shader_key& key):
39    Shader("TCS"),
40    m_tcs_prim_mode(key.tcs.prim_mode)
41 {
42 
43 }
44 
do_scan_instruction(nir_instr * instr)45 bool TCSShader::do_scan_instruction(nir_instr *instr)
46 {
47    if (instr->type != nir_instr_type_intrinsic)
48       return false;
49 
50    nir_intrinsic_instr *ii =  nir_instr_as_intrinsic(instr);
51 
52    switch (ii->intrinsic) {
53    case nir_intrinsic_load_primitive_id:
54       m_sv_values.set(es_primitive_id);
55       break;
56    case nir_intrinsic_load_invocation_id:
57       m_sv_values.set(es_invocation_id);
58       break;
59    case nir_intrinsic_load_tcs_rel_patch_id_r600:
60       m_sv_values.set(es_rel_patch_id);
61       break;
62    case nir_intrinsic_load_tcs_tess_factor_base_r600:
63       m_sv_values.set(es_tess_factor_base);
64       break;
65    default:
66       return false;
67       ;
68    }
69    return true;
70 }
71 
do_allocate_reserved_registers()72 int TCSShader::do_allocate_reserved_registers()
73 {
74    if (m_sv_values.test(es_primitive_id)) {
75       m_primitive_id = value_factory().allocate_pinned_register(0, 0);
76       m_primitive_id->pin_live_range(true);
77    }
78 
79    if (m_sv_values.test(es_invocation_id)) {
80       m_invocation_id = value_factory().allocate_pinned_register(0, 2);
81       m_invocation_id->pin_live_range(true);
82    }
83 
84    if (m_sv_values.test(es_rel_patch_id)) {
85       m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);;
86       m_rel_patch_id->pin_live_range(true);
87    }
88 
89    if (m_sv_values.test(es_tess_factor_base)) {
90       m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
91       m_tess_factor_base->pin_live_range(true);
92    }
93 
94    return value_factory().next_register_index();;
95 }
96 
process_stage_intrinsic(nir_intrinsic_instr * instr)97 bool TCSShader::process_stage_intrinsic(nir_intrinsic_instr *instr)
98 {
99    switch (instr->intrinsic) {
100    case nir_intrinsic_load_tcs_rel_patch_id_r600:
101       return emit_simple_mov(instr->dest, 0, m_rel_patch_id);
102    case nir_intrinsic_load_invocation_id:
103       return emit_simple_mov(instr->dest, 0, m_invocation_id);
104    case nir_intrinsic_load_primitive_id:
105       return emit_simple_mov(instr->dest, 0, m_primitive_id);
106    case nir_intrinsic_load_tcs_tess_factor_base_r600:
107       return emit_simple_mov(instr->dest, 0, m_tess_factor_base);
108    case nir_intrinsic_store_tf_r600:
109       return store_tess_factor(instr);
110    default:
111       return false;
112    }
113 }
114 
store_tess_factor(nir_intrinsic_instr * instr)115 bool TCSShader::store_tess_factor(nir_intrinsic_instr* instr)
116 {
117    bool two_parts = nir_src_num_components(instr->src[0]) == 4;
118 
119    auto value0 = value_factory().temp_vec4(pin_group, {0, 1, 7, 7});
120    emit_instruction(new AluInstr(op1_mov, value0[0], value_factory().src(instr->src[0], 0),
121                                  AluInstr::write));
122    emit_instruction(new AluInstr(op1_mov, value0[1], value_factory().src(instr->src[0], 1),
123                                  two_parts ? AluInstr::write : AluInstr::last_write));
124 
125 
126    if (two_parts) {
127       auto value1 = value_factory().temp_vec4(pin_group, {2, 3, 7, 7});
128       emit_instruction(new AluInstr(op1_mov, value1[0], value_factory().src(instr->src[0], 2),
129                                     AluInstr::write));
130       emit_instruction(new AluInstr(op1_mov, value1[1], value_factory().src(instr->src[0], 3),
131                                     AluInstr::last_write));
132       emit_instruction(new WriteTFInstr(value1));
133    }
134 
135    emit_instruction(new WriteTFInstr(value0));
136    return true;
137 }
138 
139 
do_get_shader_info(r600_shader * sh_info)140 void TCSShader::do_get_shader_info(r600_shader *sh_info)
141 {
142    sh_info->processor_type = PIPE_SHADER_TESS_CTRL;
143    sh_info->tcs_prim_mode = m_tcs_prim_mode;
144 }
145 
read_prop(std::istream & is)146 bool TCSShader::read_prop(std::istream& is)
147 {
148    string value;
149    is >> value;
150 
151    auto splitpos = value.find(':');
152    assert(splitpos != string::npos);
153 
154    std::istringstream ival(value);
155    string name;
156    string val;
157 
158    std::getline(ival, name, ':');
159 
160    if (name == "TCS_PRIM_MODE")
161       ival >> m_tcs_prim_mode;
162    else
163       return false;
164    return true;
165 }
166 
do_print_properties(std::ostream & os) const167 void TCSShader::do_print_properties(std::ostream& os) const
168 {
169    os << "PROP TCS_PRIM_MODE:" << m_tcs_prim_mode << "\n";
170 }
171 
TESShader(const pipe_stream_output_info * so_info,const r600_shader * gs_shader,const r600_shader_key & key)172 TESShader::TESShader(const pipe_stream_output_info *so_info, const r600_shader *gs_shader,
173                      const r600_shader_key& key):
174    VertexStageShader("TES"),
175    m_vs_as_gs_a(key.vs.as_gs_a),
176    m_tes_as_es(key.tes.as_es)
177 {
178    if (key.tes.as_es)
179       m_export_processor = new VertexExportForGS(this, gs_shader);
180    else
181       m_export_processor = new VertexExportForFs(this, so_info, key);
182 }
183 
do_scan_instruction(nir_instr * instr)184 bool TESShader::do_scan_instruction(nir_instr *instr)
185 {
186    if (instr->type != nir_instr_type_intrinsic)
187       return false;
188 
189    auto intr = nir_instr_as_intrinsic(instr);
190 
191    switch (intr->intrinsic) {
192    case nir_intrinsic_load_tess_coord_r600:
193       m_sv_values.set(es_tess_coord);
194       break;
195    case nir_intrinsic_load_primitive_id:
196       m_sv_values.set(es_primitive_id);
197       break;
198    case nir_intrinsic_load_tcs_rel_patch_id_r600:
199       m_sv_values.set(es_rel_patch_id);
200       break;
201    case nir_intrinsic_store_output: {
202       int driver_location = nir_intrinsic_base(intr);
203       int location = nir_intrinsic_io_semantics(intr).location;
204       auto semantic = r600_get_varying_semantic(location);
205       tgsi_semantic name = (tgsi_semantic)semantic.first;
206       unsigned sid = semantic.second;
207       auto write_mask = nir_intrinsic_write_mask(intr);
208 
209       if (location == VARYING_SLOT_LAYER)
210          write_mask = 4;
211 
212       ShaderOutput output(driver_location, name, write_mask);
213       output.set_sid(sid);
214 
215       switch (location) {
216       case VARYING_SLOT_PSIZ:
217       case VARYING_SLOT_POS:
218       case VARYING_SLOT_CLIP_VERTEX:
219       case VARYING_SLOT_EDGE: {
220          break;
221       }
222       case VARYING_SLOT_CLIP_DIST0:
223       case VARYING_SLOT_CLIP_DIST1:
224       case VARYING_SLOT_VIEWPORT:
225       case VARYING_SLOT_LAYER:
226       case VARYING_SLOT_VIEW_INDEX:
227       default:
228          output.set_is_param(true);
229       }
230       add_output(output);
231       break;
232    }
233    default:
234       return false;
235    }
236    return true;
237 }
238 
do_allocate_reserved_registers()239 int TESShader::do_allocate_reserved_registers()
240 {
241    if (m_sv_values.test(es_tess_coord)) {
242       m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
243       m_tess_coord[0]->pin_live_range(true);
244       m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
245       m_tess_coord[1]->pin_live_range(true);
246    }
247 
248    if (m_sv_values.test(es_rel_patch_id)) {
249       m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
250       m_rel_patch_id->pin_live_range(true);
251    }
252 
253    if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
254       m_primitive_id = value_factory().allocate_pinned_register(0, 3);
255       m_primitive_id->pin_live_range(true);
256    }
257    return value_factory().next_register_index();
258 }
259 
process_stage_intrinsic(nir_intrinsic_instr * intr)260 bool TESShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
261 {
262    switch (intr->intrinsic) {
263    case nir_intrinsic_load_tess_coord_r600:
264       return emit_simple_mov(intr->dest, 0, m_tess_coord[0], pin_none) &&
265             emit_simple_mov(intr->dest, 1, m_tess_coord[1], pin_none);
266    case nir_intrinsic_load_primitive_id:
267       return emit_simple_mov(intr->dest, 0, m_primitive_id);
268    case nir_intrinsic_load_tcs_rel_patch_id_r600:
269       return emit_simple_mov(intr->dest, 0, m_rel_patch_id);
270    case nir_intrinsic_store_output:
271       return m_export_processor->store_output(*intr);
272    default:
273       return false;
274    }
275 }
276 
do_get_shader_info(r600_shader * sh_info)277 void TESShader::do_get_shader_info(r600_shader *sh_info)
278 {
279    sh_info->processor_type = PIPE_SHADER_TESS_EVAL;
280    m_export_processor->get_shader_info(sh_info);
281 }
282 
do_finalize()283 void TESShader::do_finalize()
284 {
285    m_export_processor->finalize();
286 }
287 
read_prop(std::istream & is)288 bool TESShader::TESShader::read_prop(std::istream& is)
289 {
290    (void)is;
291    return true;
292 }
293 
do_print_properties(std::ostream & os) const294 void TESShader::do_print_properties(std::ostream& os) const
295 {
296    (void)os;
297 }
298 
299 
300 }
301